It recently came to my attention that not everyone overrides the
default merge.conflictStyle
git-config setting. So in case anyone
here wanted to try something new out that would provide more context
during a Git conflict resolution scenario here you go.
I use diff3
which you can set like this to override the default:
git config --global merge.conflictStyle diff3
When rebasing you will get the following markers:
<<<<<<< HEAD
THIS IS SOME CODE
||||||| merged common ancestors
This is some code
=======
This is some other code
>>>>>>> d5439077.....
Notice the new section from the default version between |||||||
and
======
which denotes the state that the rebased commit expected to
see.
The meaning of the diff between <<<<<<<
and |||||||
markers
remains what it used to be in the two way diff output which is the
code on the branch you are rebasing on top of and the content between
the ======
and >>>>>>>
is what you want to record on top of the
HEAD of the rebase branch.
A simple illustration
My last merge conflict arose when attempting to apply an old stash to the latest HEAD of new branch off of our mainline. It was a Nix expression conflict and looked like the following:
<<<<<<< Updated upstream
ruby = self.ruby_2_5;
||||||| merged common ancestors
nodejs = nodejs_10_22_1;
ruby = self.ruby_2_5;
=======
nodejs = nodejs_10_22_1;
#ruby = self.ruby_2_5;
>>>>>>> Stashed changes
What this is saying is that the current upstream has the following at that location of the file:
ruby = self.ruby_2_5;
When this commit was applied last that part of the upstream content looked like this:
nodejs = nodejs_10_22_1;
ruby = self.ruby_2_4;
My changes has content at that region of the file that looks like this now:
nodejs = nodejs_10_22_1;
#ruby = self.ruby_2_5;
What this is saying is that another change to the upstream branch has
removed (or moved) the nodejs
version pinning, so maybe I should
discard it (of course context matters given how Git works).
Ignoring the first line of the region around our change means we just need to decide how to resolve the line that contains the change:
<<<<<<< Updated upstream
ruby = self.ruby_2_4;
=======
#ruby = self.ruby_2_5;
<<<<<<< Stashed changes
The added context of the middle section allowed me to understand what was not relevant for resolution which we could not have confidently deduced from just a two way merge conflict context (only the top and the bottom parts of the diff above).
My resulting change was to delete the entirety of the conflict because I had merely commented out a line of Nix which means we could just delete it to get the same effect. It is also a great illustration of why commented out unused code, even just to "try" something (assuming you have the previous version in Git) hinders effectiveness and I should feel bad for this. I do! :)
Concluding thoughts
Even in a simple example, we found having this extra context in the merge conflict beneficial since it allowed us to understand what part of the conflict was relevant to resolve.
Hopefully that provided a quick illustration of how to improve effectiveness of resolving merge conflicts, even in a minimally beneficial case.
If you enjoyed this content, please consider sharing this link with a friend, following my GitHub, Twitter/X or LinkedIn accounts, or subscribing to my RSS feed.