git合并的一种合并策略是resolve:
这只能使用三向合并算法解析两个头(即当前分支和您从中拉出的另一个分支)。它试图仔细检测纵横交错的合并歧义,通常被认为是安全,快速的。
该策略似乎基于三向合并算法以及默认的递归,但与递归不同,尚不清楚它如何处理纵横交错的合并情况。
解决交叉纵横合并的算法是什么?
答案 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现在可以从存储库中读取G
(H
)的父级。提交G
存储F
的哈希ID,以便Git可以读取F
,依此类推。
当我们有两个具有单个最佳共同祖先的分支时,这往往看起来像这样:
I--J <-- branch1
/
...--G--H
\
K--L <-- branch2
从J
开始并向后工作,Git枚举了J
,然后是I
,然后是H
,然后是G
,依此类推。通过从L
开始并向后工作,Git依次列举了L
,然后依次依次为K
,H
和G
,等等。
提交H
和更早的版本位于两个分支上。提交H
是最后一个这样的提交,因此它是合并基础。因此,-s resolve
和-s recursive
都将选择提交H
作为合并基础。 (然后合并将进行新的提交M
,其父母将是 both J
和 L
。)
但并非所有图表都如此好。特别是,我们可以进行以下一系列提交:
...--G--H---K--L <-- branch1
\ /
x
/ \
...--I--J---M--N <-- branch2
要确定将哪个提交用作合并基础,Git从L
开始并向后走:L
,K
,H
-和-{{1} },J
和-G
。也就是说,Git遵循合并提交I
的和父母。同时,Git从K
开始并向后工作:N
,N
,然后是M
和-H
,依此类推。>
显然J
和H
比J
和G
好,但是没有简单的方法来打破I
之间的联系和H
是“最佳”共同祖先。这是递归和解析不同的地方。
递归策略选择两个提交作为合并基础。为此,它在提交J
和git merge
上调用内部的内部H
。此合并操作找到J
和H
的合并基础,并将它们合并以进行临时提交,该提交位于J
所在的位置。现在,该新的但临时的提交是外部合并的合并基础。
解决策略是您在主题行中提出的策略。显然,它随机选择x
或H
中的一个。您会获得哪种取决于所使用的算法,该算法未指定,并且可能会从一种Git版本更改为另一种。
解决交叉纵横合并的算法是什么?
这是J
策略,这是默认策略。如上所述,它通过合并合并库来处理它们。
您可以运行-s recursive
(具有上面的示例),您将看到两个合并基础的两个哈希ID。在某些情况下(很难绘制或就此而言难以实现),可能存在三个或更多合并基础。 (这里没有理论上的上限。)每个合并库对也可以有多个合并库。递归策略通过重复合并合并基础来处理所有这些情况,直到最终留下单个最佳(但临时)提交。
当递归合并执行递归合并时,内部合并期间发生的冲突会被悄悄地提交(带有冲突标记)到合并所使用的最终合并基础中。结果为very confusing。