2.5. Parallel Development

In centralised systems like Subversion, the only way to record a commit is at the master repository, so all parallel development must be resolved into one stream (per branch) at commit time. Mercurial lets everyone commit locally, so committed deviations can build up in the distributed repositories, and have to be resolved differently. It’s actually possible in Mercurial to have more than one "HEAD" revision on a single branch in one repository, although by default you’re not allowed to push that ambiguitiy to anyone else. This may occur because you have pulled changesets into your repository when you have other changes of your own on that branch, or that you’ve created deviating paths locally (which you can do by manually updating to a previous revision, then committing from that point, creating a split in the branch:

images/hgmultipleheads1.png

This situation could have been caused by making your own changes (green), and pulling someone elses changes from the master (orange) which were based on the same ancestor. Or, maybe the orange revisions came from a patch applied as "hg import --exact", or pulling changes from a fork.

The most common case of deviations like this is simple, short-term parallel development within the team (for more long-term deviations, see the next section). The HG Init tutorials suggest resolving this by merging the changes with your own (covered next), which is indeed the standard no-extension way to handle this, but it has one major drawback - every time it happens, in the history you have a permanent record of this divergence in the form of a split and merge of the 2 developers changes. Because this is literally an everyday occurrence of short-term deviation, this is extremely distracting when trying to decipher the history, and therefore not recommended.

Instead, by using the Rebase extension, after pulling someone elses changes you rebase your own commits so that they are re-applied on top of the head you pulled from the master, essentially flattening the history and looking like there was never any deviation, like this:

images/hgmultipleheads2.png

You can do this during the pull by appending the --rebase command (or selecting it in TortoiseHg):

hg pull --rebase

However if you’ve already got the divergence in your repository, you can rebase specifically:

hg rebase --continue

The "--continue" means that any conflicts will be resolved in your working copy, which will then need committing.

Rebase is usually automatic in the common case where the divergence has been caused by pulling from the master, but if they’ve occurred for another reason (e.g. hg import --exact) then you may need to explictly specify the rebase options. For example, in the example image, the specific command for performing the rebase is:

hg rebase -s492385cab361 -da638fcd23823 --continue

You could use the Mercurial short revision numbers instead of the "short" hashes there, but the principle is that you’re moving the base of the green revisions to the top of the orange ones. You very rarely need to use this explicit form, but that’s how you do it if you need to.

The other way of resolving 2 heads on a single branch is to merge one into the other. This preserves the history of the original deviation and then unifies the changes into a single head. As mentioned in the previouis section, you don’t want to use this approach for everyday parallel development, because it just creates a spaghetti history. However, there are less common cases where it is the best way to record the outcome of parallel development - specifically the cases where the parallel development has deviated for a reasonable time, such as Google Summer of Code and other longer-running external forks that you then want to reintegrate. Rebasing history for a period of several months isn’t appropriate because it’s highly artificial - rebase is appropriate for smoothing out the misleading splitting and merging for everyday development, but if the development really did diverge for a long time, it’s worth preserving that.

So, assuming you’ve just pulled a set of changesets from a long-running fork and you now have 2 heads, you simply want to update your working copy to your own HEAD of the branch, and issue a simple command:

hg merge

Mercurial automatically knows that you want to merge the 2 heads on this branch and will do it for you. You’ll need to resolve any conflicts if they occur, then commit the merge, unifying the heads (and being able to push them if you want), like so: images/hgmultipleheads3.png