Context
git merge considers the setting merge.conflictStyle in case of merge conflicts.
Possible values are merge (default) and diff3.
I noticed that diff3 sometimes produces much bigger conflicts (see example below).
I found this paper, which describes the diff3 algorithm in great detail, but I couldn't find much about the default merge algorithm.
Question
What are the exact differences between the merge and diff3 algorithm?
How does the default merge algorithm work exactly?
Example
I have these files:
- Base:
1
2
3
- Yours:
1
change1
change2
input1OnlyChange1
change3
change4
change5
change6
input1OnlyChange2
change7
change8
change9
2
3
- Theirs:
1
change1
change2
input2OnlyChange1
change3
change4
change5
change6
input2OnlyChange2
change7
change8
change9
2
3
With merge I get 2 conflict markers:
1
change1
change2
<<<<<<< HEAD
input1OnlyChange1
=======
input2OnlyChange1
>>>>>>> input2
change3
change4
change5
change6
<<<<<<< HEAD
input1OnlyChange2
=======
input2OnlyChange2
>>>>>>> input2
change7
change8
change9
2
3
However, with diff3 I only get 1 conflict marker:
1
<<<<<<< HEAD
change1
change2
input1OnlyChange1
change3
change4
change5
change6
input1OnlyChange2
change7
change8
change9
||||||| 0fcee2c
=======
change1
change2
input2OnlyChange1
change3
change4
change5
change6
input2OnlyChange2
change7
change8
change9
>>>>>>> input2
2
3
This is my test script (powershell):
rm -Force -r ./repo -ErrorAction Ignore
mkdir ./repo
cd ./repo
git init
# git config merge.conflictStyle diff3
cp ../../base.txt content.txt
git add *; git commit -m first
git branch base
git checkout -b input2
cp ../../input2.txt content.txt
git add *; git commit -m input2
git checkout base
cp ../../input1.txt content.txt
git add *; git commit -m input1
git merge input2
Does the merge algorithm diff the diffs again to split up the bigger conflict?
Clearly the merge algorithm also performs some kind of 3 way diff, as you don't get a conflict when you update base to match yours.
Official documentation
The docs say this:
Specify the style in which conflicted hunks are written out to working tree files upon merge. The default is "merge", which shows a
<<<<<<<conflict marker, changes made by one side, a=======marker, changes made by the other side, and then a>>>>>>>marker. An alternate style, "diff3", adds a|||||||marker and the original text before the=======marker.
Clearly this does not explain the observed difference in the example.