本文介绍了合并后Git意外还原提交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景

发现了一个长期存在的错误,并且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.

Bmaster的合并提交表明它使用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.

  1. 提交c1-Bmaster
  2. 的分支点
  3. 提交c2-master中的提交,父级:c1
  4. 提交c3-一个错误修复程序,提交A
  5. 中的该分支
  6. 提交c4-将A合并到master,父级:c2c3
  7. 提交c5-在B中提交,父级:c1
  8. 提交c6-将B合并到master.父级:c5c4
  1. Commit c1 -- the branching point of B and master
  2. Commit c2 -- A commit in master, parent: c1
  3. Commit c3 -- A bug fix commit that branch in A
  4. Commit c4 -- Merge A to master, parent: c2 and c3
  5. Commit c5 -- A commit in B, parent: c1
  6. Commit c6 -- Merge B to master. parent: c5 and c4

或者看下面的图片(在底部的前面)

Or look at the picture below (earlier on bottom)

事实已确认

  • c3仅更改一个文件f1
  • c2c5都完全不更改f1
  • c6的注释包括一个冲突列表,但不包括f1
  • c6f1还原为B版本
  • 具有以下错误的提交:c1c2c5(均是预期的),c6(也是意外的).
  • c3 changes only one file f1
  • both c2 and c5 does not change f1 at all
  • c6's comment includes a conflict list, but f1 is not included
  • c6 reverts f1 to the B version
  • Commits that have the bug: c1, c2 and c5 (all expected), c6 as well (unexpected).

软件版本

提交c3c4使用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.

根据答案进行的进一步分析和声明

  • Bmaster的合并不能快进,因为c2c5有冲突,正如我们在冲突列表中看到的那样.
  • c2c5中完成的工作位于项目的完全不同的部分(例如,该错误仅适用于台式机版本,但这些工作适用于Web版本),并且从事这些提交工作的人员通常从不希望他们应该测试错误c3修复程序.
  • 尽管删除了项目的详细信息,但图形和场景恰好代表了现实世界中发生的事情.该图是真实项目存储库中的屏幕截图.
  • The merge of B and master cannot be a fast forward since c2 is conflicting with c5, as we can see in the conflict list.
  • The work done in c2 and c5 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 bug c3 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意外还原提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-04 20:13