维基百科说,3-way合并比2-way合并更不容易出错,而且通常不需要用户干预。为什么会这样呢?

举一个3-way合并成功而2-way合并失败的例子会很有帮助。


三向合并是指在应用一个基本文件的两个更改集时合并它们,而不是应用一个更改集,然后将结果与另一个合并。

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

例如,文件a由两个人修改,一个添加驼鹿,一个添加鼠标。

#File a
    dog
    cat

#diff b, a
    dog
+++ mouse
    cat

#diff c, a
    dog
+++ moose
    cat

现在,如果我们在应用变更集时合并它们,我们将得到(3-way merge)

#diff b and c, a
    dog
+++ mouse
+++ moose
    cat

但如果我们应用b,然后看看从b到c的变化看起来就像我们把一个u变成了一个o(双向归并)

    #diff b, c
    dog
--- mouse
+++ moose
    cat

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

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

使用三向合并,它可以比较这两个文件,但也可以将它们与原始副本(在任何一方更改它之前)进行比较。所以它可以看到你删除了第一行,而你的朋友添加了最后一行。它可以使用这些信息生成合并后的版本。


这张幻灯片来自一个强制性的演示,很有趣:

The essential logic of a three-way merge tool is simple: Compare base, source, and target files Identify the "chunks" in the source and target files file: Chunks that don't match the base Chunks that do match the base Then, put together a merged result consisting of: The chunks that match one another in all 3 files The chunks that don't match the base in either the source or in the target but not in both The chunks that don't match the base but that do match each other (i.e., they've been changed the same way in both the source and the target) Placeholders for the chunks that conflict, to be resolved by the user. Note that the "chunks" in this illustration are purely symbolic. Each could represent lines in a file, or nodes in a hierarchy, or even files in a directory. It all depends on what a particular merge tool is capable of. You may be asking what advantage a 3-way merge offers over a 2-way merge. Actually, there is no such thing as a two-way merge, only tools that diff two files and allow you to "merge" by picking chunks from one file or the other. Only a 3-way merge gives you the ability to know whether or not a chunk is a change from the origin and whether or not changes conflict.


借用自AWS CodeCommit: 开发人员工具> CodeCommit > repository > RepositoryName > 拉取请求>拉取请求名称>合并