Why do changing adjacent lines but modifying independently cause a git merge conflict?

You have the right idea: Git declares a conflict if the two “sides” touch the “same lines” of the “same file”, as compared to the contents of that file in the merge base commit. The trick lies in defining same file and same line. The merge base commit in this case—given your particular commits, that is—is your first commit ever, which had test.txt with one line in it, reading Hello world!. The two branch tips have test.txt with the other contents.

Philosophically speaking, defining same file is a hard problem: see the paradox of the Ship of Theseus. Git, however, just declares that if file test.txt exists in all three commits—in the merge base, and in both branch tip commits—then this is “the same file”. So that clears that problem right up. 😀 However, “same line” is still a little fuzzy.

The change you made from the first commit ever to the first branch tip commit left line 1 alone but modified the end of the file, adding This is another line.

The change you made from the first commit ever to the second branch tip—the new master tip before the merge—changed line 1 itself.

Git gets a little squirrelly at the edges of a changed region—changes happen, in effect, between lines sometimes. Those changes touch both the above and below lines. Ultimately it’s just a quirk of the algorithm chosen to decide whether the changes conflict: Git decides to say that these changes do touch the same line(s), while a different algorithm might say they don’t.

(The edge effects arise from having to have nonempty intervals, to avoid fencepost issues. The various algorithms mostly use half-open intervals: a region starts at symbol X—lines act as symbols, here—and ends before symbol Y. The end of the file is usually assigned an EOF symbol for this purpose. Some algorithms like to have a symbol “above” the first line as well, as sort of an SOF, or Start Of File.)

Leave a Comment