August 2008 Archives

Microbranches in Mercurial, Part I: The Basics

git’s not a bad versioning system—there’s a lot to recommend it, and it’s leaps and bounds ahead of Subversion—but I’m sick and tired of seeing that the big reason to use git instead of Mercurial is because Mercurial lacks microbranching.

Wrong. Well, if you’re going to be pedantic and demand that your microbranching be accessed through a command called branch? Then sure. But you’re all smarter than that, so how about you give me some space to work here and let’s see if we can find equivalent functionality.

In Mercurial, the equivalent of git’s microbranches are called patch queues. They have a different metaphor than git branches (they’re an operational hybrid of branching and rebasing), and therefore arguably less intuitive, but if you’ve already wrapped your head around git’s index, reflog, and associated baggage, using patch queues should be a walk in the park.

What this technique is not for

Microbanching, both as it exists in git and in Mercurial as described here, is for exactly that: microbranches. Use this technique for short-lived features and thought experiments. For long-lived branches, you should continue to use full, cloned Mercurial repositories. The rich merge tracking and change history makes the mild sacrifice in hard disk space well worth it.

First, you’re going to have to enable the mq extension that ships with Mercurial and change some defaults. Open up ~/.hgrc (C:\Documents and Settings\[You]\Mercurial.ini on Windows) and ensure that you have the following lines:

[extensions]
alias=
mq=

[defaults]
diff = -p -U 8
qdiff = -U 8
qimport = -g
qrefresh = -g
qinit = -c

[alias]
qaccept = qdelete -r

[diff]
git=1

Behind the scenes, patch queues are going to be managing a series of patches, just like git does. For that reason, these options switch Mercurial’s diff format to be the same as git’s, adding a lot of extra metadata that will help with rebasing branches later on.

Next, in each repository you want to use this technique in, you’ll need to run hg qinit. This ensures that your repository has patch queues enabled.

Now, let’s say you’re working on a project called GuessMyAge. The program, if you’re curious, looks like this:

#!/usr/bin/env python
# Copyright (c) 2008 Hyperion Intergalactic Shipping Corp.  Violators will be shot.

import sys

print "Hi.  What do you think my age is?"
age = sys.stdin.readline()
print "Close enough!"

And you decide, I want to make it so that the age is only valid if it’s…a number!, which seems pretty reasonable. Instead of doing your normal hg ci/hg fetch/hg push, let’s do it with a microbranch.

First, let’s start a new patch, and a new patch.

hg qnew ageverify
hg qguard +ageverify

What’s a patch? Unlike in normal Mercurial work, where you make changes and then check them in, when working with mq, you first create a patch with which to associate your change. If you start doing work, then decide what you’re doing should be in a branch, no worries: you can simply run hg qnew -f branchname, and all existing changes will be imported into the new patch.

In order to use patches as microbranches, you also must associate a patch with a guard. The second command above creates a new guard, called ageverify, and associates it with your patch.

Now, you can start making changes. Use all Mercurial commands as usual, except that, instead of using hg ci when you’ve made changes, instead run

hg qrefresh
hg qci -m "Made some changes to GuessMyAge"

Note that the commit log message you enter here is internal to the branch, and will never show up on in the main revision history.

Meanwhile, hg in shows that some changes have been committed on the main line. You need to get back to the main branch and update. Doing that’s easy:

hg qpop -a
hg qselect -n
hg fetch

Cool. So, I want to make my branch be based off this new version. How do I do that? Simple:

hg qselect ageverify
hg qpush -a
hg qrefresh
hg qci -m "Rebased branch off of r123"

Mercurial will perform any necessary merging as normal.

You can have as many “branches” as you want this way. To jump between them, just qpop the one you’re leaving (if any) and qpush the one you want to switch to.

Meanwhile, a couple of days later, you’ve finished adding the age check

#!/usr/bin/env python
# Copyright (c) 2008-2009 Hyperion Intergalactic Shipping Corp.  Violators will be killed.

import sys

print "Hi.  What do you think my age is?"
age = sys.stdin.readline()
try:
    age = int(age)
    print "Close enough!"
except:
    print "That's not even a number!"

and you’ll probably want to merge it back into the main branch. The entire branch will appear as a single check-in within the repository’s history. To perform the merge, switch to the branch, and then issue:

# Set the commit message for the branch
hg qrefresh -m "Made GuessMyAge only say close enough if you enter a number"
# And then merge it
hg qaccept ageverify

You can then hg push the change out just as if it were any other Mercurial check-in.

Instead decide that your branch sucks and you never want to see it again? Just change out of your branch, and then issue

hg qdelete ageverify

That’s enough to get you started using microbranches for trivial exploratory features or patches. Next, we’ll look at what’s actually going on behind the scenes, and how we can use that knowledge to get something fully as powerful as git branches.


Edit: presearing at reddit noted that the original version of this article contained a series flaw. The flaws were caused because I altered the behavior some of the default mq commands to better match my personal workflow. The examples within this article have been updated to work correctly with a vanilla Mercurial install.

An Evolution of Game Art

Braid’s been receiving accolades for its amazing gameplay and complex storyline. Over at Gamasutra, I stumbled upon a great article detailing the evolution of Braid’s artwork. Especially after having beaten the game, I found it fascinating to see how the art had evolved, and had helped to give the game its unique feel.

Do Androids Dream of Electric Snakes?

Moving us one step closer to Blade Runner, I’m pleased to bring you a fully robotic water snake. Although the snake at first appears to be little more than a toy, its movements are preternaturally organic. I have a very easy time believing that I’m looking at some type of exotic life form—and I find that simultaneously amazing and frightening.

Philip K. Dick would be proud.

The Rechargeable Airplane

Although I’m not especially worried by higher fuel prices—in my opinion, they’ll help accelerate a much-needed movement to electric vehicles, which in turn will force us to use more nuclear and solar power—one of the things I’ve routinely wondered is how planes will deal with the problem. To me, the only solution seemed to be to use hydrogen (rather explosive) or increasingly expensive gas propellants. It turns out, though, that small planes can be powered by batteries—and someone has already made a battery-powered propeller plane. It’s quiet, clean, and can fly for 90 to 120 minutes—enough for a pleasure cruise. And the best part? It costs a mere 60ยข to refuel the craft.

Count me in.