Three-way git merging and meld

You may want to read updated article.

Although I am vim-lover, when it comes to git merging I use excellent tool called Meld sometimes. It's a GTK-based application written in Python and it has very nice capabilities of showing diffs. Particularly, I like how Meld shows changes on the same lines (highlighing portions of them), it's editable text pane with source highlighting and ability to visually merge conflicts using arrow icons.

But there is a snag.

I don't consider Meld as a three-way merging tool, even the authors state this on the features page. Many people tend to thing that diff tool with two panes can be considered two-way and tool with three panes as three-way. That's not the case.

Basic idea of three-way merging is taking third merging source into the loop, so instead traditional LOCAL and REMOTE (or MINE and THEIRS if you like) there is additional one: BASE. That's the parent for both commits in git. Still don't see the drawback?

For manual three-way merging you need four panes, because you want to see LOCAL, REMOTE, BASE and also the file you will be actually merging. In the git case, that would be:

test.txt
test.txt.LOCAL
test.txt.REMOTE
test.txt.BASE

Typical three-way merging tool shows differences between LOCAL, BASE and REMOTE on the top while offering one additional text pane on the bottom. For example, vimdiff can do this four-pane merging with a little tuning (you need to move merged buffer window to the bottom of the screen). Another great example of this approach is Perforce (p4merge).

Please note workflow is a bit different than in three-pane merging tools - you usually don't touch the file in the middle (BASE) and edit the bottom (merged) file manually. At least I don't know any tool that would offer you visual merging of blocks from LOCAL, BASE or REMOTE panes, except vim getdiff and putdiff capabilities. But that is not visual.

If you start three-pane merging tool (e.g. meld, kdiff3 and most of the others), you usually see LOCAL, merging file and REMOTE. What you don't see is BASE file, how it looked like before it was changed in any way.

Fortunately Meld supports tabs, so you can still see something. I configured my git to start three tabs in Meld. On the first one I see differences between BASE and LOCAL. On the second one I see BASE and REMOTE. And the third one is usual: LOCAL, merged file, REMOTE. The configuration is pretty easy:

[merge]
tool = mymeld
conflictstyle = diff3
[mergetool "mymeld"]
cmd = meld --diff $BASE $LOCAL --diff $BASE $REMOTE --diff $LOCAL $MERGED $REMOTE

You don't even need to set conflict style to "diff3" if you dont like to see "merged common ancestors" in the conflict block, but I like to see it there. This line is optional thus. And how does it look like? The first tab shows the changes in the branch I am merging into (e.g. "master"):


The second is similar, shows changes from the branch I am merging (e.g. "feature" branch):


And the third (opened by default) has traditional three-pane layout where I do the work.


That's all for today.
comments powered by Disqus
twitter.com linkedin.com
google.com/+ facebook.com
flickr.com youtube.com