问题描述
场景
发现了一个长期存在的错误,并且bisec发现了有问题的提交.因此,错误修复程序创建了一个分支(例如分支A
),仅针对所有标记和此后的发行版,可以合并此分支以修复该错误.然后将A
合并到master
.一切都很好.
A long existing bug was spotted out and the problematic commit was found by bisec. So the bug fixer created a branch (say branch A
), just for all the tags and releases after this point can merge this branch to fix the bug. A
was then merged to master
. Everything is fine.
后来,另一个在分支B
上工作的开发人员将分支合并到master
.此后,我们发现该错误又回来了.
Later on, Another developer that works on branch B
merged the branch to master
. After this point, we found that the bug was back.
从B
到master
的合并提交表明它使用B
的版本,因此可以有效地还原错误修复程序.
The merge commit for B
to master
shows that it uses B
's version and so it effectively reverts the bug fix.
提交历史记录
以下是按时间排序的,排在最前面.
The following is ordered by time, earlier on top.
- 提交
c1
-B
和master
的分支点 - 提交
c2
-master
中的提交,父级:c1
- 提交
c3
-一个错误修复程序,提交A
中的该分支 - 提交
c4
-将A
合并到master
,父级:c2
和c3
- 提交
c5
-在B
中提交,父级:c1
- 提交
c6
-将B
合并到master
.父级:c5
和c4
- Commit
c1
-- the branching point ofB
andmaster
- Commit
c2
-- A commit inmaster
, parent:c1
- Commit
c3
-- A bug fix commit that branch inA
- Commit
c4
-- MergeA
tomaster
, parent:c2
andc3
- Commit
c5
-- A commit inB
, parent:c1
- Commit
c6
-- MergeB
tomaster
. parent:c5
andc4
或者看下面的图片(在底部的前面)
Or look at the picture below (earlier on bottom)
事实已确认
-
c3
仅更改一个文件f1
-
c2
和c5
都完全不更改f1
-
c6
的注释包括一个冲突列表,但不包括f1
-
c6
将f1
还原为B
版本 - 具有以下错误的提交:
c1
,c2
和c5
(均是预期的),c6
(也是意外的).
c3
changes only one filef1
- both
c2
andc5
does not changef1
at all c6
's comment includes a conflict list, butf1
is not includedc6
revertsf1
to theB
version- Commits that have the bug:
c1
,c2
andc5
(all expected),c6
as well (unexpected).
软件版本
提交c3
和c4
使用git 1.9.4.msysgit.0,其他使用1.9.5.msysgit.0.
Commit c3
and c4
was using git 1.9.4.msysgit.0, others was 1.9.5.msysgit.0.
此推送使用的是SourceTree 1.6.14.0.
The push was using SourceTree 1.6.14.0.
问题
是什么原因引起的问题?如何避免这种情况?由于f1
上的更改是较新的更改,因此我看不出git应该使用较旧版本而不标记出冲突的任何原因.
What causes the problem? How to avoid this? Since the change on f1
is more recent, I can't see any reason that git should use an older version without marking a conflict.
根据答案进行的进一步分析和声明
-
B
和master
的合并不能快进,因为c2
与c5
有冲突,正如我们在冲突列表中看到的那样. - 在
c2
和c5
中完成的工作位于项目的完全不同的部分(例如,该错误仅适用于台式机版本,但这些工作适用于Web版本),并且从事这些提交工作的人员通常从不希望他们应该测试错误c3
修复程序. - 尽管删除了项目的详细信息,但图形和场景恰好代表了现实世界中发生的事情.该图是真实项目存储库中的屏幕截图.
- The merge of
B
andmaster
cannot be a fast forward sincec2
is conflicting withc5
, as we can see in the conflict list. - The work done in
c2
andc5
are on a quite different part of the project (say, the bug is apply to desktop version only but those work is for web version) and people worked for those commits usually never expect that they should test the bugc3
fixes. - Although the detail of the project was removed, the graph and the scenario exactly represents something that happened in the real world. The graph is a screenshot from the real project repository.
推荐答案
原则上,让我们来看一下将B合并到master时(在修复了错误之后),以及是否在任何版本中均未触及带有bugfix的文件B的提交,git应该进行快速合并并保留较新的,已经固定的文件.如果文件被修改,它将尝试进行自动合并,并且如果出现冲突,它将迫使您在允许合并之前使用某些合并工具(例如kdiff3或meld)解决冲突.
Let's see, in principle, when merging B to master (after the bug has been fixed), and if the file with the bugfix was not touched in any of B's commits, git should do a fast-forward merge and keep the newer, already fixed file. If the file was modified, it will try to do an automatic merge, and if a conflict appears and it would force you to use some merge tool like kdiff3 or meld to solve the conflict prior to letting you merge.
如果您确定文件在B的所有历史记录中都从未被触及过,那么这确实有点奇怪,因为它应该使文件远离主文件.
If you are sure that the file was never touched in all of B's history, this is kind of strange, indeed, as it should keep the one from master.
无论如何,为了避免这种情况,如果分支是私有分支,则我更喜欢在合并之前始终进行重新设置.也就是说,将B重新设置到主机的头部,以确保它包含最后的错误修正,并确保它可以正确地使用这些错误修正(也许通过修复错误,有人破坏了会影响B功能的某些东西).测试完所有内容之后,使用最后的错误修复程序和我的代码,我将B合并为master.
Anyway, to avoid this sort of stuff, I prefer to do always a rebase prior to merging, if the branch is a private branch. That is, rebase B to the master's head, to be sure it contains last bugfixes, and to be sure it works correctly with those bugfixes (maybe by fixing a bug, somebody broke something that would affect B's functionality). After testing everything, using the last bugfixes and my code, I'd merge B to master.
如果B是公共分支,而不是变基,则您可能希望将master合并到B,对其进行测试,然后将B合并回master.
If B is a public branch, instead of a rebase, you may want to merge master onto B, test it, and then merge B back to master.
这些技巧在这篇文章中得到了很好的解释:
These tricks are very well explained on this post:
http://blog.sourcetreeapp.com/2012/08 /21/merge-or-rebase/
遵循这个人的规则,您可能再也不会遭受git-madness了:)
Follow this guy's rules and you'll probably never suffer git-madness anymore :)
这篇关于合并后Git意外还原提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!