There was an item noted in comments in another question that now redirects here (How to setup git merge / git pull for xml files?). Logically, this too should be a comment, but it really needs formatting. So, here it is as an answer, with this subject:
Setting merge.conflictStyle
to diff3
can be helpful
Doing:
git config --global merge.conflictStyle diff3
(or the same without --global
if you want it just for one repository, but I prefer the --global
myself) can make the work-tree copy more useful. Note that if you are writing a merge driver, you do not get the work-tree copy as an input. Instead, you get the three files, ours
base
and theirs
, as your three inputs. This is primarily useful if you aren't trying to write your own merge driver (and writing your own is tricky: if it were easy, XML merge would have been solved quite a while ago).
Example
Here are the example inputs from the other posting:
$ cat base
<li>
<span>BA</span>
</li>
$ cat ours
<li>
<span>BA</span>
</li>
<li>
<span>CE</span>
</li>
$ cat theirs
<li>
<span>BA</span>
</li>
<li>
<span>DF</span>
</li>
We can now see how Git will merge these files, using git merge-file
, which is the command line equivalent of one low-level (file-level) operation from a git merge
:
$ cp ours current
$ git merge-file current base theirs
$ cat current
<li>
<span>BA</span>
</li>
<li>
<<<<<<< curr
<span>CE</span>
=======
<span>DF</span>
>>>>>>> theirs
</li>
Here, as you can see, Git has pointed out that the changes in ours
(copied to current
) conflict with the changes in theirs
as compared to base
. However, some parts of the conflict were easy to resolve, so Git did that, and marked only the remaining parts of the conflict.
When we request a diff3
style merge, however, we get this:
$ cp ours current
$ git merge --diff3 current base theirs
$ cat current
<li>
<span>BA</span>
</li>
<<<<<<< curr
<li>
<span>CE</span>
</li>
||||||| base
=======
<li>
<span>DF</span>
</li>
>>>>>>> theirs
There are two differences. Not only does Git add the ||||||| base
section—which in this case, is empty; there are no lines in the merge base input—but it also stops doing a partial resolution of the changes in ours
/ current
with those in theirs
.
(This is necessary since Git now has to show "ours vs base" and "theirs vs base" rather than just "ours vs theirs, after best effort".)