你什么时候会使用不同的Git合并策略?

When would you use the different git merge strategies?

在Git合并的手册页上,您可以使用许多合并策略。

  • 决心——这只能使用三向合并算法解析两个头(即当前分支和从中提取的另一个分支)。它试图仔细检测纵横交错合并的歧义,一般认为是安全和快速的。

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

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

  • 我们的-这将解析任意数量的头,但合并的结果始终是当前的分支头。它旨在取代分支机构的旧发展历史。

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

我应该在什么时候指定与默认值不同的内容?每种方案的最佳方案是什么?


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

递归的

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

章鱼

当我有几棵树需要合并时,我就用章鱼。您可以在大型项目中看到这一点,在这些项目中,许多分支都有独立的开发,并且已经准备好合并成一个单一的头。

一个章鱼分支只要能够干净利落地完成任务,就可以在一次提交中合并多个头部。

为了举例说明,假设您有一个项目有一个主控形状,然后有三个要合并的分支(称为A、B和C)。

一系列递归合并如下所示(请注意,第一个合并是一个快进合并,因为我没有强制递归):

series of recursive merges

然而,一只章鱼的合并看起来是这样的:

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

octopus merge

我们的

我们的==我想换个脑袋,但把脑袋带来的所有变化都扔掉。

这样可以保持分支的历史,而不受分支的任何影响。

(阅读:它甚至没有看到这些分支之间的变化。分支只是合并,对文件不做任何操作。如果您想合并到另一个分支中,每次出现"我们的文件版本或它们的版本"问题时,都可以使用git merge -X ours

子树

如果要将另一个项目合并到当前项目的子目录中,子树非常有用。当您有一个不想作为子模块包含的库时很有用。


实际上,如果您想放弃分支带来的更改,您只需要选择我们的两个策略,但要将分支保留在历史中;如果您要将独立项目合并到超级项目的子目录中(如"git"存储库中的"git gui"),则需要保留子树。

当合并两个以上分支时,章鱼合并会自动使用。这里的解决方法主要是出于历史原因,以及当您遇到递归合并策略角的情况时。


"解析"与"递归"合并策略

递归是当前默认的两个头策略,但是经过一些搜索,我终于找到了一些关于"解析"合并策略的信息。

摘自O'Reilly Book版本控制与Git(Amazon)(释义):

Originally,"resolve" was the default strategy for Git merges.

In criss-cross merge situations, where there is more than one possible merge basis, the resolve strategy works like this: pick one of the possible merge bases, and hope for the best. This is actually not as bad as it sounds. It often turns out that the users have been working on different parts of the code. In that case, Git detects that it's remerging some changes that are already in place and skips the duplicate changes, avoiding the conflict. Or, if these are slight changes that do cause conflict, at least the conflict should be easy for the developer to handle..

我已经成功地使用默认递归策略失败的"resolve"合并了树。我收到了fatal: git write-tree failed to write a tree个错误,多亏了这个博客帖子(mirror),我尝试了"-s resolve",它起到了作用。我还是不太清楚为什么…但我认为这是因为我在两个树中都有重复的更改,并且正确地解决了"跳过"它们的问题。