Say I start out with one commit on master in test.txt
with just the line Hello world!
followed by a new line (to prevent any diffs happening on the first line when adding a second line).
Then, I branch off this commit with branch name modification
. Here I change the file from
Hello world!
to
Hello world!
This is another line.
and then I commit to that branch.
Then I check out master and change the file from
Hello world!
to
Hello world! This is a new thing.
And then I commit that onto master
. In summary, in both commits, I just change one line. Since I had the newline on master at the beginning, the extra commit on master
only modifies line 1, while the commit on modification
only modifies line 2. Hence, I don't see why this results in a merge conflict when I try to merge modification
into master. However, I get this as the diff3
output.
<<<<<<< HEAD
Hello world! This is a new thing.
||||||| merged common ancestors
Hello world!
=======
Hello world!
This is another line.
>>>>>>> modification
Why wouldn't git realize that they're changing separate lines and merge those two together? I would think it would take line 1 modification from the commit on master
and the line 2 modification on modification
to form:
Hello world! This is a new thing.
This is another line.
The only possibility I can think of is there's something about modifying the same hunk regardless of the line number.
Interestingly, if instead on modifications
I add This is another line.
to line 3 instead of line 2, keeping that empty line on the modification
branch, the merge continuous without conflicts.
I recently learned that when merging two branches in git, if there are changes on two adjacent lines git declares this a conflict. For example, if file test.txt has this content: and then attempt to merge testing into master, git declares a merge conflict. My naive expectation was that the merge would happen without conflict and yield this:
I recently learned that when merging two branches in git, if there are changes on two adjacent lines git declares this a conflict. For example, if file test.txt has this content: and then attempt to merge testing into master, git declares a merge conflict.
In order to avoid causing such problems, git usually refuses to automatically merge changes touching nearby lines. It gives you a chance to verify whether the program logic would be broken or not.
The ======= line is the “center” of the conflict. All the content between the center and the <<<<<<< HEAD line is content that exists in the current branch master which the HEAD ref is pointing to. Alternatively, all content between the center and >>>>>>> new_branch_for_merge_conflict is content that is present in our merging branch.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With