为什么三向合并优于双向合并?

Joh*_*ner 147 version-control merge conflict three-way-merge

维基百科称3向合并不像双向合并那样容易出错,而且通常不需要用户干预.为什么会这样?

3向合并成功并且双向合并失败的示例将是有帮助的.

JW.*_*JW. 235

假设您和您的朋友都检出了一个文件,并对其进行了一些更改.您在开头删除了一行,而您的朋友在最后添加了一行.然后他提交了他的文件,你需要将他的更改合并到你的副本中.

如果您正在进行双向合并(换句话说,差异),该工具可以比较这两个文件,并看到第一行和最后一行是不同的.但它怎么会知道如何处理差异呢?合并版本是否应包含第一行?它应该包括最后一行吗?

通过三向合并,它可以比较两个文件,但它也可以将它们与原始副本进行比较(在您更改之前).所以它可以看到你删除了第一行,并且你的朋友添加了最后一行.它可以使用该信息来生成合并版本.

  • @Harry 说原著有三行(ABC)。它从我朋友的副本(ABCD)开始,并将其与我的副本(BC)进行比较。如果没有看到原文,它可能会认为我把A和D都去掉了,最后的结果应该是BC。 (35认同)
  • **“但是它怎么知道如何处理这些差异呢?”** 不明白。如果它已经可以看到两个文件之间的差异(不参考原始文件),为什么它不能按文件时间戳的升序顺序应用这两个更改?也就是说:它从我朋友提交的副本开始,将其作为(新的)原始副本(在顶部添加行),然后在其顶部应用我的本地更改(在底部删除行)。 (2认同)
  • @Harry,如果每个文件都有自共同祖先以来带时间戳的更改列表,那么您将进行三向合并。您描述的方法需要将文件倒回到共同祖先,以便按时间顺序应用差异。换句话说,我不确定“两个文件之间的时间戳差异而不引用共同祖先”是否有明确的含义。 (2认同)

Von*_*onC 69

这张幻灯片从一个Perforce呈现有趣的是:

幻灯片图片

三向合并工具的基本逻辑很简单:

  • 比较基本文件,源文件和目标文件
  • 识别源文件和目标文件文件中的"块":
    • 与底座不匹配的块
    • 与基地匹配的块
  • 然后,汇总一个合并的结果,包括:
    • 在所有3个文件中彼此匹配的块
    • 在源或目标中与基础不匹配但不在两者中都不匹配的块
    • 与基础不匹配但彼此匹配的块(即,它们在源和目标中的更改方式相同)
    • 冲突块的占位符,由用户解决.

请注意,此图中的"块"纯粹是象征性的.每个都可以表示文件中的行,或层次结构中的节点,甚至是目录中的文件.这完全取决于特定合并工具的功能.

您可能会问三向合并相对于双向合并有什么优势.实际上,没有双向合并这样的东西,只有工具可以区分两个文件并允许你通过从一个文件或另一个文件中挑选块来"合并".
只有3向合并才能让您知道块是否是来自原点的更改以及更改是否发生冲突.

  • 然而,在 Git 中进行 4 路合并是很常见的,其中基础实际上并不相同。仍然是 3 路合并更好,2 路。 (2认同)

The*_*ire 19

一种三向合并,其中两个变更集到一个基础文件在应用时合并,而不是应用一个,然后将结果与另一个合并.

例如,在同一位置添加一行的两个更改可以解释为两个添加,而不是一行的更改.

例如

文件a已由两个人修改,一个添加驼鹿,一个添加鼠标.

#File a
    dog
    cat

#diff b, a
    dog
+++ mouse
    cat

#diff c, a
    dog
+++ moose
    cat
Run Code Online (Sandbox Code Playgroud)

现在,如果我们在应用变更集时合并变更集,我们将获得(3路合并)

#diff b and c, a
    dog
+++ mouse
+++ moose
    cat
Run Code Online (Sandbox Code Playgroud)

但是如果我们应用b,那么看看从b到c的变化看起来我们只是将'u'改为'o'(双向合并)

    #diff b, c
    dog
--- mouse
+++ moose
    cat
Run Code Online (Sandbox Code Playgroud)


pab*_*blo 19

我写了一篇非常详细的帖子.基本上你不能用双向,非常非常无效的方式跟踪删除/添加.

  • 我建议你复制并粘贴你文章的部分内容.我认为这将有助于您获得upvotes,并将更加符合stackoverflow的理念. (2认同)