I’ve recently started to experiment with distributed source control systems for my personal repository. I had been using Subversion previously, but it had several issues with directories that bothered me. In addition, since my primary computer was a laptop, I also wanted to have full commit and change tracking when I was offline.
So distributed source control systems seemed to fit the bill. I looked at two systems in particular, Mercurial and git. Mercurial caught my eye because of its simplicity, and similarity with the traditional, centralized SCMs such as CVS and Subversion. However, I actually started using git first. The reason was that many open source projects had switched to git and I needed to compile several bleeding edge packages. So, I had no choice but to learn to use git. However, I couldn’t really wrap my head around it. While git is no doubt, a very powerful SCM, it was also a very complicated SCM. I took me a good hour or so before I understood how to track branches.
So, I settled for Mercurial. While I was worried that Mercurial was too immature, the fact that the Mozilla projects are also using Mercurial was very comforting.
Usage, Tips and Tricks
I will not describe the setup and typical usage of Mercurial, since there are plenty of good tutorials out there. What I will do, is highlight some of the features that have really caught my eye and I find indispensible now.
The first great feature of Mercurial is the addremove command, which removes deleted files and adds newly created files to the repository. The command also has an optional parameter which you can specify the directory to process. I typically use ., such that my next commit would only contain the changes that I’ve made in the current directory.
hg addremove #For the entire repository hg addremove . #For the current directory
Another nice feature of Mercurial is its ability to ignore certain files and file patterns specified using a single .hgignore file. This is very convenient, for excluding temporary files, such as the intermediary files that are left behind after compiling LaTeX source code. Mercurial supports two syntax types when specifying patterns in .hgignore, glob and regex. The glob syntax allows you to specify patterns using wildcards (*). I primarily use regex, since regular expressions are very powerful.
Here are the contents of my current .hgignore:
syntax: regexp .*.swp .*.swo ^results/.* ^projects/.*/bin/ ^lab/[0-9][0-9](winter|spring|fall)/.+\.(log|glo|glg|gls|dvi|aux|bm|bbl|blg|brf|ist|lof|lot|out|toc|vrb|ps)
After creating the .hgignore file, don’t forget to add it to the repository for tracking using:
hg add .hgignore
Tracking Branches
For those interested in how to track branches using git, here is the command that I used. the -b modifer creates a branch in the local repository. The checkout command further require the origin/ prefix for branches. In addition, the --track modifier tracks the remote branch such that a future pull will retrieve updates from the branch.
Using Mercurial:
hg co somebranch
Using git:
git checkout --track -b localbranch origin/somebranch
Update on git
Thanks to the comment by Jakub, tracking a remote branch is actually rather easy using the git remote command. Here is an example I had to do with retrieving a xf86-video-ati git repository.
git remote add agd5f git://cgit.freedesktop.org/~agd5f/xf86-video-ati/
To restrict the remote repository to a particular branch, use -t like the following:
git remote add agd5f -t agd-powerplay git://cgit.freedesktop.org/~agd5f/xf86-video-ati/
We can now fetch data from the remote repository using the command:
git fetch agd5f
We can list the branches that are present in our repository by executing the command. Note that the remote repository shows up just like a separate branch to our local repository:
git branch -r
Now, we can pull from this remote repository, and merge the changes from the branch agd-powreplay:
git pull agd5f agd-powerplay
Restoring a Single File to a Previous Revision
It seems that Mercurial is currently not able to checkout a single file or subdirectory. It is one of the “todo” items in their Google Summer of Code project this year, so perhaps we’ll have this feature soon enough. However, this is rather inconvenient at the moment. A workaround for this issue is to use the hg cat command, to view a previous revision of a file. In my case, I had overwritten a file applet.svg with changes that I did not want to keep. To revert the file, I executed:
hg cat applet.svg > applet.svg
Tags
In Mercurial, tags are simply aliases for changesets.
hg checkout -r tagname
git treats tags, branches and trunk/master as one and the same, in the sense that they are all refspecs. This is similar to Subversion’s model, however, tags and branches aren’t simply another directory in the repository. You have to add the tags/ prefix when checking out a tag:
Using git:
git checkout -b localtag tags/remotetag
Conclusions
I am very happy with Mercurial. I ran into a very annoying issue with Mercurial early on, when I executed hg fetch, and it used my repository URI, along with my username and password as a commit message. However, luckily this issue was fixed in the Mercurial 1.0 release. Admittedly, I’ve only been using a single person Mercurial repository for the past couple months, so I haven’t really experienced a situation where I needed the full power of a SCM. However, Mercurial has been so far, been smooth sailing.









In defense of Git:
Hi Jakub,
Thanks for your comments. It’s great to know there is a “git remote” command. I haven’t had much experience with branches on Mercurial, since I am using it primarily as a personal repository though, while git has been with large open-source projects. The scale and complexity of my usage differ vastly between the two SCMs. So, I would say my experience using git and Mercurial is indeed very biased.
Do you think that the hour that you spent learning git was actually more about learning how Distributed SCMs work in general?
In this case, learning Mercurial was easier just because you had already learnt git
I’m using git for my own repository too and, after I understood the principles, I am enjoying it very much!
Hi Thiago,
You’re right that the time I spent learning git, I also spent learning how distributed SCMs worked. However, I really find git’s syntax very strange. Perhaps, that was my biggest gripe with it.
Mercurial had a familiar syntax, which allowed me to perform the basic operations without requiring any prior knowledge of distributed SCMs. This allowed me to have a functional repository, while allowing me to incrementally learn the additional features that a distributed SCMs provides.
Well, I’ll be sure to ask you whenever I have a question regarding git
And I liked, will be looking at your site.