Git合并策略是什么“解决”策略?

时间:2020-02-04 02:42:02

标签: git git-merge

git合并的一种合并策略是resolve

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

该策略似乎基于三向合并算法以及默认的递归,但与递归不同,尚不清楚它如何处理纵横交错的合并情况。

解决交叉纵横合并的算法是什么?

1 个答案:

答案 0 :(得分:2)

首先,让我们注意什么是“交叉交叉合并”。在Git中,分支名称只是标识了属于该分支的 last (或 tip )提交。分支中其余的提交是通过遵循该提交的父级,其父级的父级(祖父母),后退一步的父级(曾祖父母)等等来确定的:

... <-F <-G <-H   <--branch

这里的分支名称branch标识的提交的真实哈希ID很大而又丑陋,但我们将其称为H。也就是说,Git读取名称branch的内容:

$ git rev-parse branch
<some big ugly hash ID here>

Git使用该哈希ID从存储库读取提交H。提交H表示其父提交是另一个看起来很丑陋的随机哈希ID,但我们将其称为G,因此Git可以使用H来查找G的哈希ID。 Git现在可以从存储库中读取GH)的父级。提交G存储F的哈希ID,以便Git可以读取F,依此类推。

当我们有两个具有单个最佳共同祖先的分支时,这往往看起来像这样:

          I--J   <-- branch1
         /
...--G--H
         \
          K--L   <-- branch2

J开始并向后工作,Git枚举了J,然后是I,然后是H,然后是G,依此类推。通过从L开始并向后工作,Git依次列举了L,然后依次依次为KHG,等等。

提交H和更早的版本位于两个分支上。提交H是最后一个这样的提交,因此它是合并基础。因此,-s resolve-s recursive都将选择提交H作为合并基础。 (然后合并将进行新的提交M,其父母将是 both J L。)

但并非所有图表都如此好。特别是,我们可以进行以下一系列提交:

...--G--H---K--L   <-- branch1
         \ /
          x
         / \
...--I--J---M--N   <-- branch2

要确定将哪个提交用作合并基础,Git从L开始并向后走:LKH-和-{{1} },J和-G。也就是说,Git遵循合并提交I父母。同时,Git从K开始并向后工作:NN,然后是M和-H,依此类推。

显然JHJG好,但是没有简单的方法来打破I之间的联系和H是“最佳”共同祖先。这是递归和解析不同的地方。

递归策略选择两个提交作为合并基础。为此,它在提交Jgit merge上调用内部的内部H。此合并操作找到JH的合并基础,并将它们合并以进行临时提交,该提交位于J所在的位置。现在,该新的但临时的提交是外部合并的合并基础。

解决策略是您在主题行中提出的策略。显然,它随机选择xH中的一个。您会获得哪种取决于所使用的算法,该算法未指定,并且可能会从一种Git版本更改为另一种。

解决交叉纵横合并的算法是什么?

这是J策略,这是默认策略。如上所述,它通过合并合并库来处理它们。

您可以运行-s recursive(具有上面的示例),您将看到两个合并基础的两个哈希ID。在某些情况下(很难绘制或就此而言难以实现),可能存在三个或更多合并基础。 (这里没有理论上的上限。)每个合并库对也可以有多个合并库。递归策略通过重复合并合并基础来处理所有这些情况,直到最终留下单个最佳(但临时)提交。

当递归合并执行递归合并时,内部合并期间发生的冲突会被悄悄地提交(带有冲突标记)到合并所使用的最终合并基础中。结果为very confusing