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.