git 为什么合并后GIT说“已经是最新的”,但分支之间的差异仍然存在?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15736564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why after merge does GIT say "Already up-to-date", but differences between branches still exist?
提问by Peter Snow
I was originally working in 'newfeature' branch and I was called to fix a bug on the live branch urgently. I created a branch for that called 'generalmaintenance', did the job and then switched to develop and merged it in. I now want to return to 'newfeature' branch and to merge in the changes that I merged into it earlier.
我最初在“新功能”分支工作,我被要求紧急修复实时分支上的错误。我为此创建了一个名为“generalmaintenance”的分支,完成了这项工作,然后切换到开发并将其合并。我现在想返回到“newfeature”分支并合并我之前合并到它的更改。
When I switched to 'newfeature' and merged in 'develop', there were conflicts in 3 files.
当我切换到 'newfeature' 并合并到 'develop' 时,有 3 个文件存在冲突。
I got in a tangle resolving the conflicts and eventually decided to use the "Revert" command in the 'Team' menu of Aptana Studio 3 (which is my IDE). I expected this to roll me back to before the merge, which it appears to have done.
我陷入了解决冲突的纠结中,最终决定使用 Aptana Studio 3(这是我的 IDE)的“团队”菜单中的“恢复”命令。我希望这能让我回到合并之前,它似乎已经完成了。
Anyway, when I merge in 'develop' again, it says, Already-up-to-date
, but when comparing files between the two branches, they are very different and the changes I added in the other branch are not being merged in.
无论如何,当我再次合并“开发”时,它说,Already-up-to-date
但是当比较两个分支之间的文件时,它们非常不同,并且我在另一个分支中添加的更改没有被合并。
How will I merge the two branches now please?
请问我现在如何合并这两个分支?
回答by eddiemoya
Reverting Merges vs. Resetting Merges
恢复合并与重置合并
My guess is that you actually areAlready-up-to-date
.
我的猜测是你实际上是Already-up-to-date
。
The problem is that git revertdoesn't undo the merge, it only undoes the changes that the merge brought with it. When you create a merge commit, you're combining the commit histories of those two branches.
问题是git revert不会撤消合并,它只会撤消合并带来的更改。创建合并提交时,您将合并这两个分支的提交历史记录。
Merging
合并
develop
|
A---B---C
\ \
E---F---M
|
newfeature
In the case above, develop
is merged into newfeature
, creating the M
commit. If you were to run git log newfeature
you would see all the commits from both branches, however from the perspective of the newfeature
branch, all those changes were performed by the M
commit.
在上面的情况下,develop
被合并到 中newfeature
,创建M
提交。如果您要运行,git log newfeature
您会看到来自两个分支的所有提交,但是从分支的角度来看newfeature
,所有这些更改都是由M
提交执行的。
Reverting
还原
The git revert
command does not remove any commits, instead it creates a new commit that undoes the changes that the commit contained. For example if you had a commit containing this diff...
该git revert
命令不会删除任何提交,而是创建一个新提交来撤消提交所包含的更改。例如,如果您有一个包含此差异的提交...
-This is the old sentence.
+This is the new sentence.
Then reverted this, the revert command would create a new commit that just preformed the opposite diff, it simply flips the signs.
然后恢复这个,revert 命令将创建一个新的提交,它只是执行相反的差异,它只是翻转符号。
-This is the new sentence.
+This is the old sentence.
This is really useful for undoing damage caused by commits that other developers already have. It moves history forward rather than changing history.
这对于消除由其他开发人员已经拥有的提交造成的损害非常有用。它推动历史前进,而不是改变历史。
Reverting Merges
恢复合并
However, in the context of a non-fastforward merge it may have an undesired effect.
但是,在非快进合并的上下文中,它可能会产生不良影响。
develop
|
A---B---C
\ \
E---F---M---W
|
newfeature
Assuming W is a reversion commit, you can see how running git log newfeature
will still include all the commits from the develop branch. As a result, additional merges from develop
will no work, because it doesn't see anything missing from your branch.
假设 W 是一个回滚提交,您可以看到 runninggit log newfeature
将如何仍然包含来自 develop 分支的所有提交。因此,其他合并 fromdevelop
将不起作用,因为它看不到您的分支中缺少任何内容。
Using git resetinstead of revert.
使用git reset而不是 revert。
In the future, you might want to consider using git reset --hard <ref>
(where <ref>
is the commit hash of the merge) to undo a merge if that merge has not been shared with other developers. In the example above, after having created merge commit M
, running the command git reset --hard F
would result in the following.
将来,如果该合并尚未与其他开发人员共享,您可能需要考虑使用git reset --hard <ref>
(其中<ref>
是合并的提交哈希)来撤消合并。在上面的示例中,创建合并提交后M
,运行该命令git reset --hard F
将导致以下结果。
develop
|
A---B---C
\ \
E---F---M
|
newfeature
As you can see this technique doesn't obliterate the commit as some people tend to think, it simply moves your branch back to the commit you selected. Now if you ran git log newfeature
you would only get commit F
, E
, and A
. Now the merge is actually gone from your branches history, so a later attempts to re-merge in develop
will cause no problems.
正如您所看到的,这种技术并没有像某些人认为的那样消除提交,它只是将您的分支移回您选择的提交。现在,如果你跑了git log newfeature
,你只会得到承诺F
,E
和A
。现在合并实际上已经从你的分支历史中消失了,所以以后重新合并的尝试develop
不会导致任何问题。
This method is not without its complications. Realize that you are now modifying history, so if the newfeature
branch was pushed to a remote branch after the M
merge was made, then git is going to think you are simply out of date and tell you that you need to run git pull
. If its just you working on that remote branch, then feel free to force-push
- git push -f <remote> <branch>
. This will have the same effect of the reset but on the remote branch.
这种方法并非没有并发症。意识到您现在正在修改历史记录,因此如果在合并newfeature
后分支被推送到远程分支M
,那么 git 会认为您只是过时并告诉您需要运行git pull
. 如果只是您在该远程分支上工作,那么请随意force-push
- git push -f <remote> <branch>
。这将具有与重置相同的效果,但在远程分支上。
If this branch is being used by multiple developers, who would have by now already pulled from it - then this is a bad idea. This is the very reason git revert
is useful, because it undoes changes without changing the actual history.
如果这个分支被多个开发人员使用,他们现在已经从它中拉出来了 - 那么这是一个坏主意。这就是很有用的原因git revert
,因为它可以在不改变实际历史的情况下撤消更改。
Using reset on history is really only on option for commits that have not been shared.
在历史上使用重置实际上仅适用于尚未共享的提交。
The solution - reverting the reversion.
解决方案 - 还原还原。
If the merge commit has already been shared, then the best approach is probably to use git revert
on that merge. However as we said before, you can not then simply merge the branch back in and expect all the changes from that branch to re-appear. The answer is to revert the revert commit.
如果已经共享了合并提交,那么最好的方法可能是git revert
在该合并上使用。但是,正如我们之前所说,您不能简单地将分支合并回并期望该分支的所有更改重新出现。答案是还原还原提交。
Lets say you did some work on the develop
branch after having revered the merge in newfeature
. Your history would look something like this.
假设您develop
在newfeature
. 你的历史看起来像这样。
develop
|
A---B---C---D
\ \
E---F---M---W
|
newfeature
If you merge develop
into newfeature
now, you would only get D
because its the only commit that is not already part of the history of the newfeature
branch. What you also need to do is revert that W
commit - git revert W
should do the trick followed by git merge develop
.
如果合并develop
到newfeature
现在,你只会得到D
,因为它的唯一的承诺,是不是已经是历史的一部分newfeature
分支。您还需要做的是还原该W
提交 -git revert W
应该执行git merge develop
.
develop
|
A---B---C-----------D
\ \ \
E---F---M---W---M---G
|
newfeature
This restores all the changes made by the original merge commit - which were actually made by C
and B
but were reverted in W
, it then brings in D
via a new merge commit G
I would recommend reverting the revert beforemerging in the recent changes to develop
, I suspect doing it in that order will have a lower chance of triggering conflicts.
这将恢复原始合并提交所做的所有更改 - 这些更改实际上是由C
并B
恢复的W
,然后D
通过新的合并提交引入我G
建议在合并最近的更改之前恢复恢复develop
,我怀疑这样做以该顺序触发冲突的可能性较低。
TL;DR
TL; 博士
Reverting creates a 'revert commit'. When undoing a revert, you need to run the revert command on the revert commit that was created when you reverted the first time. It should be easy enough to find, git tends to auto-comment on reverts so that they start with the word "Reverted".
还原会创建“还原提交”。撤消还原时,您需要对第一次还原时创建的还原提交运行 revert 命令。它应该很容易找到,git 倾向于对还原进行自动评论,以便它们以“还原”一词开头。
git revert <commit>
git revert <commit>
回答by Katti
Found a hacky solution. But it works.
找到了一个hacky解决方案。但它有效。
Whatever eddiemoyahas answered is totally helpful. Thanks a lot for explanation. I encountered the similar situation. Where, I was able to see a lot of content in git diff <branch>
but git merge was saying already up to date.
无论eddiemoya回答了什么,都非常有帮助。非常感谢您的解释。我遇到了类似的情况。在哪里,我能够看到很多内容,git diff <branch>
但 git merge 说已经是最新的。
And I was not able to find the exact revert commit due to lot of reverts in the log. (Yeah bad thing. Shouldn't have happened in the first place)
由于日志中有很多还原,我无法找到确切的还原提交。(是的,坏事。一开始就不应该发生)
Solution
解决方案
git checkout branchX -- .
This will stage all the changes from branchX to my current branch. Use on of your favorite git client, unstage and revert whatever is not intended.
这会将所有更改从 branchX 转移到我当前的分支。使用您最喜欢的 git 客户端,取消暂存并还原任何不想要的东西。
Make a new commit and be happy :)
进行新的提交并感到高兴:)