Here’s another advent blog series! This time it’s from Kamal Marhubi and it’s on the subject of Mercurial. It’s pretty interesting, especially for giving a fresh perspective on Mercurial’s user experience.
The introduction post lays down some of what makes Mercurial interesting (phases, changeset evolution, extensibility) while the third post catches up to another cool thing (revsets, one of my favourite Mercurial features) that was missing from that initial list.
Extensions and papercuts
There’s a good article in the series about how Mercurial’s reliance on extensions (and more specifically the need to explicitely enable them) is one of the several “papercuts” you get when you start using it. This reminded me of Josef Sipek’s “Modern Mercurial” blog series which starts with an article precisely about that problem:
Then it suddenly hit me —- before these tweaks, I had been using Mercurial like it’s still 2005!
I think this is a very important observation. Mercurial didn’t seem to be improving because none of the user-visible changes were forced onto the users.
The problem is that the Mercurial devs have an extremely strict approach to how the CLI should behave, and how no breaking changes should ever be introduced. This means that:
- No “dangerous” commands should be accessible by default (“_don’t give the
user opportunities to shoot their own foot_”), which explains why history
rewriting commands like
rebaseare disabled out-of-the-box.
- Things that were later added (like colours, pager support, etc.) were often done in an optional extension to not break previous behaviour.
Arguably, these strict rules are partially the reason why the Mercurial CLI is so nice to use compared to other CLIs like Git’s, but they’re also obviously causing a lot of pain elsewhere.
I naively think this might be somewhat fixable by:
- Making the first
hgrun setup some sane default if it doesn’t find any user
.hgrc(i.e. better bootstrapping).
- Relaxing some of the strict CLI rules by realizing that most use-cases that
rely on specific historical behaviours (like automated scripts) are already
most probably setting environment variables like
HGPLAIN, in which case Mercurial can disable some of the more “human facing” features.
But of course, it’s lot more complicated than this… and to some degree, this
was addressed with the
tweakdefaults setting (formerly known as “friendly
hg”), but, ironically enough, you still need to know about enabling
it, since it default to
false, of course.
The fourth post talks about how Mercurial doesn’t have a staging area (a.k.a. index) like in Git.
It’s kind of funny to me that we have people who started with Git as their first (and sometimes only) VCS, and it will soon dawn on them that, frankly, there’s nothing out there quite like Git’s index (well, at least not in any of the half-dozen VCSes I’ve used so far). Git’s pretty unique on that front.
Although I don’t recommend trying to emulate a tool’s idiosyncratic workflow when using another tool, people coming from Git invariably ask about this so there’s always been some partial answer for Mercurial. A few years ago, the MQ extension was that answer (it kinda gives you something that looks like multiple staging areas!), but it seems that most of the Mercurial community has moved away from it (I have too). MQ is still available for those who want it, but these days it seems that using secret phases and history rewriting is more common (and it also kinda gives you multiple staging areas too!).
I don’t really do that, but I imagine it would work along the lines of:
[alias] newstage = commit -s -m "STAGING AREA" upstage = commit --amend
So when you start working on something new, you push your work-in-progress with
hg newstage into a secret commit called “
STAGING AREA”. Since it’s secret,
it won’t get pushed and will stay local. Then, as you keep working, you run
upstage every now and then to “grow” that commit. When it’s ready, you change
that commit’s phase to
draft. It’s a bit clunky (there are 2 aliases when
ideally there would be only one) but you get the idea, and with a bit of
scripting I’m sure that it’s possible to get it down to a similar UX as Git’s.
Twelve days to go
Anyway, we’re still half-way to Christmas so check out Kamal’s blog for the rest of the series (assuming he keeps it going :) ).