Over the past couple of years, since David Roundy handed over control of the darcs revision control system to a talented team of developers, it has come a long way in stability and performance.

I began using darcs essentially out of necessity, simply because it was the revision control system of choice for much of the Haskell community. I have always found my use of it to be somewhat clunky, and lately I’ve been migrating most of my remaining Haskell projects away from it.

In day to day use, in a single-developer repository on a single machine, darcs has always been pretty decent, and in fact a few aspects of its user interface have been influential. Its record command, for instance, is sufficiently nifty that I wrote the record extension for Mercurial. I’m fairly sure that my enthusiasm for record also led me to ask for the feature that became the interactive change selection feature of the marvelous TortoiseHg GUI. Even git acquired a similar change selection feature at some point.

However, for a team of developers, or even a single individual working across several machines, darcs isn’t so great. It presents two challenges that I find troublesome: dealing with concurrent conflicting changes to files is a mess, and its much-touted patch theory often makes poor engineering sense.

My idea of a good merge process is the one I get with Mercurial (git and svn can be configured to act similarly, but don’t present nearly as nice a default experience). In brief: I start a merge by hand, most of it proceeds automatically, and I get dropped into a nice GUI whenever something funky needs fixing up. With darcs, dealing with conflicts is messy, confusing, and something I usually get wrong. I’m not alone in this; several of my collaborators dread submitting patches to GHC because it’s so hard to merge changes against a fast-moving upstream. After enough bad experiences, I have a subconscious view of a darcs merge as a way to lose bits of work.

As for patch theory, my principal point of discomfort with it is that I have little idea what was in someone’s repository when they created a patch. People grouse about the fact that the history of a Mercurial project often contains a lot of merges, but those merges mean that I can reconstruct what another developer was able to see when they were writing code. That’s a long way to say "merges are debugging gold", especially when coupled with liberal use of the bisect command. The rebase command provided by git and Mercurial provides a nice balance: history is explicit by default, but can be tidied if necessary.

I am not by any means trying to belittle the work of the darcs developers. Darcs is a good piece of software, and I appreciate the work its team has put into it over the past few years. I’ve soldiered along with it for long enough that I could obviously do so indefinitely, but the experience I have with other tools is now sufficiently better that I simply don’t want to use darcs. For day to day work, TortoiseHg is the best GUI I’ve had the good fortune to use with any revision control tool. It makes committing changes and browsing history a snap. And for collaboration, of course both github and bitbucket are fabulous. I particularly appreciate the hg-git plugin, which lets me collaborate almost seamlessly with git users, while enjoying Mercurial’s UI. Unfortunately, the darcs community has nothing on a comparable level of quality for either fluid use or collaboration.