Using Mercurial

This page represents a quick guide to using Mercurial. For a more complete guide, I recommend Mercurial: The Definitive Guide by Bryan O'Sullivan.

Creating a repository

If an Eclipse project already exists: (assume it is present in a directory called myprogram)
cd ~/eclipse_work/myprogram
hg init
The hg init command sets up a local Mercurial repository. Alternatively, if you are using an online repository, to start your project you would begin by cloning the repository. Then you can create a new Eclipse project by importing the directory you set up.

Updating the local repository

Once the local repository is in place, there are two different types of updates to perform. First, files in the directory are not automatically present in the repository. Hence, whenever a new file is added, use the hg add command to add it to the repository. No filename argument is required; every file in the directory not already present in the repository will be added. Once you are ready to commit changes to the local repository, use hg commit. In a multi-person project, use hg commit -u userid; that way, the person who committed changes can be identified readily. Each commit will require a comment describing the changes that have been made. You can view the history of commits using hg log.

Switching back to an old version

If you are unhappy with the current version in your local repository and you would like to revert to an earlier version, you can use hg revert. If, for example, your current revision is version 15, and you would like to revert to version 10, you would type:
hg revert --all --rev 10
This will create "version 16" which is identical to version 10. The --all forces all files to revert; if you only want to revert some of them, list the appropriate filenames.

Incorporating changes from the central repository

Once your local version is satisfactory, you will want to combine it with the work performed by the other members of your team. To retrieve the current contents of the central respository, use hg pull. This command creates a new "head" in your repository; it does not combine the code with yours. To combine the code, use hg merge right after hg pull. If all files can be merged automatically, Mercurial will do so. If Mercurial cannot handle the merge, you will have to perform the merge manually. On our machines, gvimdiff is employed for this purpose. Once the merge process is complete, use hg commit to finalize the merge. As it can be annoying to type all three of these commands together, there is an option to combine them into a single command: hg fetch. To enable fetching, add the following code to your .hg/hgrc file:
[extensions]
fetch = 
That's right; there's nothing after the assignment symbol. It's in the standard distribution, but not enabled by default.

Using gvimdiff

The gvimdiff program uses the diff mode of the vim editor to resolve merge conflicts. You do not need to be fluent in using vim to use gvimdiff effectively; all the necessary commands will be presented below. When gvimdiff starts up, you will be presented a window with three panels: your version of the file, the repository's version of the file, and an attempted merge of the two files. Your job is to resolve all ambiguities in the merged version. As a working example, I will show how to merge two short text files: demo1.txt and demo2.txt. A very common scenario in a merge is to prefer one version over the other. In this case, we just want to copy the preferred file into the merged file. Click on the desired version, then type :diffput 3 (and Enter). This copies everything over, as you can see below:

Screenshot: Using diffput

In some cases, we want to copy certain lines from one of the files into our merged file. In this case, click on the merged file's panel. Then type :[line-number]diffget [buffer-number]. In the example below, typing :3diffget 2 copies line 3 from buffer 2 into the merged buffer.

Screenshot: Copy a line

The diffget command differs from diffput only regarding the "perspective" from which changes happen. If your cursor is in the originating window, use diffput; if your cursor is in the destination window, use diffget. In this example, diffget is employed to copy the entirety of buffer 2 into the merged buffer:

Screenshot: using diffget

Rather than copying one line at a time, a range of lines can also be copied. The syntax for this is :[line1,line2]:diffget [buffer-number]. In this example, the first two lines from buffer 1 are copied into buffer 3 using the command :1,2:diffget 1:

Screenshot: Copying multiple lines with diffget

Once the merged version is satisfactory, use :wqa to save everything and exit:

Screenshot: Saving and closing

Of course, once your merge is complete it is essential to sanity-check your work. In particular, you should compile the code and run the unit tests to make sure everything is in order.

Updating the central repository

Once your local version is satisfactory, and you have merged in the changes from the main branch, you can update the central repository with the command hg push. Before doing a push, common courtesy requires that all of the code:
  1. Compiles; and
  2. Passes all unit tests.
When you push, Google Code may request your password. If you get sick of typing your password, add it to your .hg/hgrc as follows:
[paths]
default = https://userid:password@code.google.com/p/project/