How can I make git merge produce more granular conflicts when using `merge.conflictstyle diff3`?

tl;dr Your expected behavior is an invalid diff3 representation of the conflict. You can't have both.


The original commit explains in excruciating detail. I'll try to summarize.

Let's look at your case. You started with this.

# ancestor

# main
line1
line2
line3
line4
line5

# feature
line1
line2
line
line4
line5

You asked for a diff between all three files, and that's what you got.

<<<<<<< HEAD
line1
line2
line3
line4
line5
||||||| 2952256
=======
line1
line2
line
line4
line5
>>>>>>> feature

The original file is blank. HEAD changed it to added five lines. feature added five lines. That's a correct representation of the 3-way conflict.

Let's look at what you expect to see...

line1
line2
<<<<<<< HEAD
line3
||||||| 2952256
=======
line
>>>>>>> feature
line4
line5

This says the original file contained 4 lines. HEAD and feature added a line between line2 and line4.

In other words, it says you merged these files.

# ancestor
line1
line2
line4
line5

# main
line1
line2
line3
line4
line5

# feature
line1
line2
line
line4
line5

That is not true, the ancestor was blank.

The reduction you want is fine for 2-way conflict markers, but would defeat the point of 3-way conflict markers.


Git 2.35.0 will have a new conflict style that behaves exactly as desired here called zdiff3. It can be configured with git config merge.conflictstyle zdiff3. Add --global to configure the conflict style globally.

I tested it with git version 2.35.0.rc0 and it produces the following result.

line1
line2
<<<<<<< HEAD
line3
||||||| 59df1b4
=======
line
>>>>>>> feature
line4
line5

Perfect!