Why is a 3-way merge advantageous over a 2-way merge?
Asked Answered
F

4

259

Wikipedia says a 3-way merge is less error-prone than a 2-way merge, and often times doesn't need user intervention. Why is this the case?

An example where a 3-way merge succeeds and a 2-way merge fails would be helpful.

Folse answered 8/11, 2010 at 23:14 Comment(0)
F
379

Say you and your friend both checked out a file, and made some changes to it. You removed a line at the beginning, and your friend added a line at the end. Then he committed his file, and you need to merge his changes into your copy.

If you were doing a two-way merge (in other words, a diff), the tool could compare the two files, and see that the first and last lines are different. But how would it know what to do with the differences? Should the merged version include the first line? Should it include the last line?

With a three-way merge, it can compare the two files, but it can also compare each of them against the original copy (before either of you changed it). So it can see that you removed the first line, and that your friend added the last line. And it can use that information to produce the merged version.

Fiden answered 8/11, 2010 at 23:36 Comment(3)
"But how would it know what to do with the differences?" Didn't get it. If it can already see the differences between the two files (without reference to the original), why can't it apply both changes serially in increasing order of files' timestamps? That is: It starts off with my friend's committed copy taking it to be the (new) original (with the line addition at the top) and then, on top of it, applies my local changes (line deletion at the botton).Abstention
@Abstention Say the original had three lines (ABC). It starts with my friend's copy (ABCD), and compares it to mine (BC). Without seeing the original, it might think that I removed both A and D, and that the final result should be BC.Fiden
@Abstention if each file had a list of timestamped changes since the common ancestor, you would have a 3-way merge. The method you described would require rewinding the file back to the common ancestor in order to apply the diffs chronologically. Phrased differently, I'm not sure there's an unambiguous meaning to "a timestamped diff between two files without reference to a common ancestor."Hispanic
J
125

This slide from a perforce presentation is interesting:

slide image

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.

Jesher answered 9/11, 2010 at 5:21 Comment(8)
"whether or not changes conflict." - doesn't 2-way merge (diff) shows a conflict as well (though the info is lost as of the source of the conflict)/Slavocracy
It's however common in Git to have a 4-way merge where the base is actually not the same. Still a 3-way merge is better and 2-way.Mayweed
@Wernight, Is there a 5-way merge?Snowblind
@Snowblind Not that I know of, but that's what is actually happening during a git cherry-pick, or rebase.Mayweed
Very detailed and useful explanationRimester
@Qwerty This is more about configuring the merge conflict visualization. The merge itself is three-way already with Git: https://mcmap.net/q/21332/-what-are-two-and-three-way-diff-mergeJesher
My git was doing two way merges without having it set explicitly as in the linked answer. An I thought that when someone reads this, they might be interested in knowing how to enable it right away. EDIT: Okay I understand, of course the merge was always three way. I will delete and repost the comment, since I can't edit it now, so can you.Ricker
How to configure git to see 3-way merge diffs in diff tool https://mcmap.net/q/21333/-how-can-i-see-a-quot-three-way-diff-quot-for-a-git-merge-conflictRicker
N
36

A three-way merge is where two changesets to one base file are merged as they are applied, as opposed to applying one, then merging the result with the other.

For example, having two changes where a line is added in the same place could be interpreted as two additions, not a change of one line.

For example, file a has been modified by two people, one adding moose, one adding mouse.

#File a
    dog
    cat

#diff b, a
    dog
+++ mouse
    cat

#diff c, a
    dog
+++ moose
    cat

Now, if we merge the changesets as we apply them, we will get (3-way merge)

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

But if we apply b, then look at the change from b to c it will look like we are just changing a 'u' to an 'o' (2-way merge)

    #diff b, c
    dog
--- mouse
+++ moose
    cat
Need answered 8/11, 2010 at 23:30 Comment(0)
S
-2

In day-to-day work, we would do or rather let git do a 2-way merge whenever possible. The question would be why is a 3-way merge needed, instead of the default 2-way merge.

The default merge strategy is a fast-forward merge(see left picture below), but if git can't do a fast-forward merge because the development history has diverged, example extra-commits has been committed to the source branch(but not by you), git has to do some work and it uses a three-way merge (right picture below). A recommended read can be found here. Of course, with all things git, you can also decide to do a 3-way merge by using the option --no-ff, even when it is not required.

enter image description here

Borrowed from AWS CodeCommit: Developer Tools > CodeCommit > Repositories > RepositoryName > Pull requests > Pull request name > Merge

Speos answered 16/6, 2021 at 2:51 Comment(3)
In the picture, which line refers to the source branch, and which one refers to the designation branch?Dissatisfactory
The source is the black dots, the blue dots are what are being added, and the white dot is the resulting merge.Speos
This answer is not even remotely close to answering the question "Why is a 3-way merge advantageous over a 2-way merge?".Catie

© 2022 - 2024 — McMap. All rights reserved.