什么时候使用不同的git merge策略?


429

在git-merge的手册页中,可以使用多种合并策略。

  • resolve-使用三路合并算法只能解析两个头(即当前分支和您从中拉出的另一个分支)。它试图仔细检测纵横交错的歧义,并且通常被认为是安全且快速的。

  • 递归 -这只能使用3向合并算法解析两个磁头。当可以用于三向合并的公共祖先不止一个时,它将创建公共祖先的合并树,并将其用作三向合并的参考树。据报道,通过对来自Linux 2.6内核开发历史记录的实际合并提交进行的测试,可以减少合并冲突,而不会引起错误合并。此外,这可以检测和处理涉及重命名的合并。当拉或合并一个分支时,这是默认的合并策略。

  • 章鱼 -可以解决两个以上的问题,但拒绝执行需要手动解析的复杂合并。它主要用于将主题分支头捆绑在一起。当拉或合并多个分支时,这是默认的合并策略。

  • 我们的 -可以解析任意数量的头,但是合并的结果始终是当前分支头。它旨在取代侧支的旧开发历史。

  • 子树 -这是一种修改的递归策略。合并树A和B时,如果B对应于A的子树,则首先调整B以匹配A的树结构,而不是读取相同级别的树。对公共祖先树也进行了此调整。

什么时候应该指定不同于默认值的内容?每个方案最适合什么情况?

Answers:


305

我对解决方法不熟悉,但是我使用了其他方法:

递归的

递归是非快进合并的默认设置。我们都熟悉那个。

章鱼

当我有几棵需要合并的树时,我使用了章鱼。您可以在较大的项目中看到这一点,在该项目中,许多分支机构都进行了独立开发,并且所有这些都准备在一起。

章鱼分支可以一次提交地合并多个头,只要它可以干净地进行即可。

为了举例说明,假设您有一个具有母版的项目,然后合并了三个分支(分别称为a,b和c)。

一系列递归合并看起来像这样(请注意,第一次合并是快速进行的,因为我没有强制递归):

一系列递归合并

但是,单个章鱼合并将如下所示:

commit ae632e99ba0ccd0e9e06d09e8647659220d043b9
Merge: f51262e... c9ce629... aa0f25d...

章鱼合并

我们的

我们的==我想另当别论,但抛弃了头脑所带来的所有变化。

这样可以保留分支的历史记录,而不会影响分支。

(阅读:甚至没有看过这些分支之间的变化。这些分支只是合并而对文件没有任何作用。如果要合并到另一个分支中,并且每次出现“我们的文件版本或它们的文件版本版本”,您可以使用git merge -X ours

子树

要在另一个项目中合并到当前项目的子目录中时,子树很有用。当您拥有不想作为子模块包含的库时,此选项很有用。


1
那么,Ocotopus唯一真正的优势是减少了树中的合并提交数量?
奥托

60
您无需指定章鱼合并策略:如果合并两个以上的分支(git merge A B ...),则会自动使用它。
JakubNarębski09年

抱歉,出现问题了,但是制作这些屏幕截图的工具是什么?它看起来像是分支历史的非常好/漂亮的可视化……
Bernd Haug,2010年

4
gitg适用于Linux环境。
Akash Agrawal 2014年

2
这个提示-X ours很棒,只是节省了我一个小时的工作。
迈克尔

49

实际上,如果您要放弃分支带来的更改,但是将分支保留在历史记录中,则只有两种策略是我们的策略;如果要将独立项目合并到超级项目的子目录中,则可以选择子树(例如“ git”存储库)。

合并两个以上的分支时,会自动使用章鱼合并。 在这里解决问题主要是由于历史原因,以及当您被递归合并策略的极端情况所打击时。


对于有致命git-write-tree错误的两头合并,我必须选择“解析”而不是默认的“递归”。“解决”策略完全合并。这可能与要合并的分支中移动许多文件有关。
thaddeusmt

@thaddeusmt:有趣。您能否(如果可能)将有关此“递归”合并策略失败的错误报告发布到git邮件列表中?提前致谢。
JakubNarębski2012年

@JakubNarębski我不确定如何收集足够的信息来提交有意义的错误报告,对不起,我是Git的n00b。正如我在此处的答案(stackoverflow.com/a/10636464/164439)中提到的那样,我的猜测是与我重复两个分支中的更改有关,并且“解决”在跳过重复的更改方面做得更好。
thaddeusmt 2012年

@JakubNarębski现在您也可以选择他们的,这与《我们的反面》手册中的内容相同。它们都不是为您自动选择的。愿您可以稍作更新,添加他们的选项
SebNag

3
@SebTu:没有theirs合并策略(即--strategy=theirs),但是theirs默认的recursive合并策略(即--strategy=recursive --strategy-option=theirs-Xtheirs)是可选的。
雅库布·纳伦斯基(JakubNarębski)'02

23

“解决”与“递归”合并策略

递归是当前的默认两头策略,但是经过一番搜索,我终于找到了有关“解决”合并策略的信息。

摘自O'Reilly的《使用Git的版本控制》亚马逊)(措辞如下):

最初,“解决”是Git合并的默认策略。

在交叉合并的情况下,存在多个合并基础的情况下,解决策略的工作方式如下:选择一个可能的合并基础,并希望获得最佳合并。实际上,这并不像听起来那样糟糕。经常发现,用户一直在处理代码的不同部分。在这种情况下,Git会检测到它正在合并一些已经存在的更改,并跳过重复的更改,从而避免了冲突。或者,如果这些微小的变化确实引起冲突,则至少冲突应该易于开发人员处理。

我已经使用“解析”成功合并了树,但默认递归策略失败了。我遇到了fatal: git write-tree failed to write a tree错误,并且感谢这篇博客文章mirror),我尝试了“ -s resolve”,它可以正常工作。我仍然不确定为什么……但是我认为这是因为我在两棵树上都有重复的更改,并解决了“跳过”它们的问题。


我正在使用3向合并(p4merge),并且在递归合并失败时将冲突写入.BASE文件。在这种情况下,回退到解决策略很有帮助。
mrzl 2012年


-2

由于上述答案并未显示所有策略细节。例如,有些答案是缺少有关进口细节resolve选项和recursive它有许多子选项ourstheirspatiencerenormalize,等。

因此,我建议您访问官方git文档,其中解释了所有可能的功能:

https://git-scm.com/docs/merge-strategies

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.