This weekend I reviewed some old trac tickets and found one that had a fix in a support script, released over a year ago, and a related change that would provide a performance improvement to the web application. The change, which was never tested, was in a diff file created in the containing directory, so it had no path or file info in it. The diff was attached to the ticket. Once I figured out what source file it was, I desperately wanted to have the old Teamware Filemerge from Solaris which afaik no longer exists. I tried the Apple Filemerge, but if it knows how to do a three-way merge, it wasn’t obvious to me (not that I read any documentation). I googled and found mentions of a rewrite of the old fm in python but it had been abandoned some years ago. I googled some more and found a few other tools to try, one of which turned out to be perfect: kdiff3.
I am so grateful to whoever wrote this tool! (Joachim Eibl) I’ll have to go back and see if it is shareware or something and send them money if it is. (Done.) It is exactly what I was looking for, and performed the three-way diff, correctly auto-merging the parallel changes when I gave it the common ancestor copy of the file, the version used to make the patch (which I got by applying the patch to the old version referenced in the ticket), and the current version of the file from trunk. Plus, the interface was easy to use. I could step through the diffs and select the version that I wanted to keep in the merged result in a way that was very clear. The task can be inherently confusing, so getting the interface right is quite an accomplishment.
It may not win any visual design awards, but I give it a gold star for user experience.
In case you do not appreciate the significance of a three way merge, where one file is known to be the common ancestor (kdiff3 calls it the “base”), the advantage is that the tool can tell you what lines were added and what lines were deleted. When you compare just two files, it is not possible to tell whether one file added a new line or the other file deleted that line. When you compare each to a common ancestor, you can tell definitively what happened.