So my relative dislike of any mergetool that I've tried (list below) has me slowly coding my way to one of my own. I think it's a doable task, now that I've nearly got the [exceptionally simplistic] diff engine close to done. A good mergetool seems to be mostly about the UI, honestly. Can I tell what I'm doing, what's in the current file I'm about to check back in, and the source of each of those edits? Can I tell that I've handled each conflict?

I've got a number of ideas of what's really needed -- saves of past unconflict sessions, quick summations of how much of each file (local, remote, base) you've put into the unconflicted file, the ability to look at the file's history beyond local/remote/base into other branches and farther back in history, etc -- and that's largely GUI driven. I might need a middleware tier for interfacing with git, but that's about it for the faceless code.

The UI, on the other hand, is going to be a bear.

Anyhow, doing this in Mono so that it's crossplatform is both exceptionally cool and horribly painful. Cool in that the faceless C# code really does work great no matter where I run it. Cool in that my code, all written in MonoDevelop on OS X, "just runs" when I opened it in Visual Studio 2010 for fun today. I'm inserting a screenshot, just because it's crazy cool how easily the Mac developed code opens in Microsoft-land.

(Note that it's obviously not close to done yet; still just playing with the diff engine and learning how to do everything in Windows.Forms programmatically -- no RAD designers in MonoDevelop for Windows.Forms.  Gtk#, sure.  Windows.Forms, no.)

The pain I've documented largely already. You'll notice no highlighting in that screenshot; just colored text. That's b/c highlighting doesn't work on Mono's Windows.Forms for Mac. Nor do ToolStrips. Nor does every menu accelerator. It's a mess.

Just for fun, I'll include a Mac screenshot here... I don't have it handy, so I'll include the one from sourceforge for now.  For some bizarre reason, their system added a horrible black border around the image to make it look like it's on an old TV.  Go figure.

Which means I'll eventually need to use MonoMac -- a bridge between Mono code and native UIs designed in XCode -- to finish up a quality unconflict for OS X. And since it appears so much of a good mergetool is UI, that means a lot of repeated logic.

Oh well. For now, I'll just use the ugly lowest common denominator of Windows.Forms on OS X, then fork like mad when I get to a good stopping point.

Final thought for now: Writing the diff engine is actually pretty neat. Makes you appreciate what mergetools and diff functions are really doing. You'll notice the "-1" out in front of some lines. That means those lines "didn't change", relatively speaking. That's the wrong way to do a diff. Initially I had way too much of a file-centric approach to diffs, and not diff-centric enough. Working on that. And to do it right, you have to make at least two passes through the code to work out when what's moved has changed order or not.

mergetools I've tried and not really liked:

WinMerge: No three-way merge. Leaves crappy files to clean up. Not updated in a long time, and the rewrite seems dead.
p4merge: Great ideas, poor implementation.  Love the icons, but I can't always see them.  Also hard, with current highlight scheme, to see what I've inserted and what's an option for inserting.  No hard confirm on saves.
FileMerge: Two-way merge, poorly done, at least when SourceTree calls it.  Works fine (aka, "reliable"), I guess, but featureless.
vimdiff: Good, but though I love VIm in general, I'm newbie enough to merging files to want to to use a mouse and have more helpful UI cues than just highlighted colors over what amount to tiled xwindows.
kdiff3: For some reason, I can't get this to integrate correctly. Using something as a mergetool should be easy. Few are. I don't think this is always saving when and where I think it's saving (same deal with WinMerge and p4merge at times), and often (likely b/c of a flaw in my script, I guess) isn't opening when it's called from cmd line or the git GUI I'm using. Also a little bit of a stodgy interface.

Labels: , , ,