None

Merging with Mercurial

November 28, 2009

When working with the Mercurial version control system, each person has their own repository. This makes it possible for users to work offline and still have access to all the version history. It also means that each person has a backup copy of the entire repository on their machine.

When you're happy with the build you have, then you push your changes to a central repository. When you want other people's changes, you pull from that same central repository.

Note: Although I'm talking about a "central repository" here, you don't need one to use mercurial, you can pass changes directly between users. We use a central one that everyone pushes to; it works for us.

Creating a repository is simple:

hg init

At this point you can do hg add to add new files, and hg commit to commit them. This works really well, and it's all you need if there's only one person working on the project.

The fun and games comes when you have more than one person working on the source. In this situation, you'll need to do some merging.

Lets say you've committed a change to your local repository, and you want to pick up the changes other people have made to make sure your changes are good.

hg pull /path/to/central/repos

will fetch the changes from the shared respository into your local copy. What sometimes happens here is that there are some central changes that clash with changes you've made. In this case the repository creates two heads, which you'll need to merge together.

$ hg pull /home/tjs/tmp
pulling from /home/tjs/tmp
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)

The key thing about this output is the indication that it has created new heads. Run hg heads to show that there are now two:

$ hg heads
changeset:   2:88203c9cac6f
tag:         tip
parent:      0:ec1bb18bfd4c
user:        tjs@local
date:        Sat Nov 28 22:55:28 2009 +0000
summary:     Added another line

changeset:   1:b1466a62b447
user:        tjs@local
date:        Sat Nov 28 22:55:48 2009 +0000
summary:     Changed testfile to add second line

We need to merge these two heads together. Once we've done that we can then push the combined changes back to the central server.

Run hg merge to merge them together:

$ hg merge
merging testfile
This Vim was not compiled with the diff feature.
merging testfile failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon

This would normally show a diff, but I don't have any diff software installed. Edit testfile manually at this point, and change it so that it is how you want it to be, merging the two conflicting changes. Once you're happy, mark the file as merged with hg resolve --mark and commit. We will now have only one head.

$ hg resolve testfile -mark
$ hg commit
$ hg heads
changeset:   3:48e2ae6fa930
tag:         tip
parent:      1:b1466a62b447
parent:      2:88203c9cac6f
user:        tjs@local
date:        Sat Nov 28 23:02:09 2009 +0000
summary:     Merge

The repository has now been merged, so you can safely test the code then push it back out to the central repository.