Mercurial Primer

I am a source control nut, I’ve been speaking about Subversion for years, I co-lead an active open source project which uses git and GtiHub, and I’ve also dabbled with Bazaar. So far I’m feeling the limits of Subversion, loving the code-hosting features of some of the DVCS tools, and hating git and github in equal measure (don’t bother to try to talk me out of this, I’m well aware the problems are mostly on my side). I don’t know anyone else using Bazaar in the PHP community but I do know quite a few people raving about Mercurial, or Hg. This post is a quick introduction to the commands I have been using since I started trying out Hg and BitBucket for myself.

The .hgrc file

This holds the configuration settings for Mercurial, and lives on *nix systems in ~/.hgrc. Mine contains:

[ui]
; editor used to enter commit logs, etc. Most text editors will work.
editor = vim
username = Lorna Mitchell

hg clone

Bitbucket actually shows you the command to clone right on the project page, which I think is a nice touch. And it is literally this simple :) Clone creates the local repo and working directory for you, and you are ready to go.

hg status

Coming from a Subversion background, Mercurial’s status command feels like coming home. It simply shows what has been added, modified, removed, obstructed or whatever, using most of the same symbols as SVN does. It also adds changed files automatically which may or may not annoy you depending on how you work – I don’t mind that. Changes shown in status are changes not committed yet.

hg commit

Like so many of the other version control systems, you can add a -m switch to hg commit to put your message in on the command line if you wish:
hg commit -m "eliminating single-character variable names from the views"

hg add

Simply add the paths (or patterns) to the files you want to add, and mercurial will add them and show them with an “A” next to them in hg status.

hg remove

Delete files that are currently being tracked by mercurial – if you see an exclamation mark in your hg status list, that’s an obstruction and means you deleted a file without telling mercurial to do it for you. Fix this with hg revert:

hg revert

This command puts the name file(s) back to how they were at the last commit. So if you have added, removed or changed a file, this will be undone by the revert command. Check status again afterwards to make sure things look as you expect.

hg diff

Shows content differences since the last commit. Bear in mind that it does not show property differences so changes in hg status may not result in the files showing in hg diff. You can also diff between revisions and repositories as you wish.

hg log

Shows the change history for this repository. Mercurial uses both numeric and hash identifiers for its revisions, and automatically tags the most recent local revision with the name “tip”.

hg update

Pulls in changes from another repository – if you don’t specify otherwise this will be the respository you originally cloned, but since this is a distributed system, you can actually pull changes in from anywhere.

hg push

Pushes your changes back to the repo you cloned. Remember that you’ll need the relevant security in place to do this, although it is possible to save passwords and other settings in ~/.hgrc

Now for a few bonus tips, maybe not commands you use every day but ones I really really like!

hg archive [path]

The archive command does the equivalent of svn export, but for mercurial. Simply specify a path and mercurial takes a snapshot of your local repo and places it there with no version control information in it. Useful for deployment tasks.

hg outgoing and hg incoming

I’ve been pretty excited since falling over these commands – they tell you which changes are in your local repo ready to be pushed, and which are in the remote repo ready to be pulled in – basically a simple diff between the locations. I really like this feature! (If anyone knows how to do this in git, I’d be grateful!)

Mercurial Primer

That was a quick starter-for-ten on the mercurial usage front, I think this is a great tool as it has all the features of a distributed system but is simple and easy to use, especially for those coming from Subversion. There is a great mercurial tutorial from Joel Spolsky and the Selenic FAQs are also excellent.

If you have additional tips or want to share your mercurial experiences, add a comment!

9 thoughts on “Mercurial Primer

  1. Hah, I feel the exact same way! At my company, we’ve converted to Mercurial-only. I’m contributing to two separate projects on Github, but Mercurial is just that much more intuitive to use. I <3 Mercurial.

  2. Thanks for the summary Lorna. It annoys me to no end that people so blindly choose the popular Git, when it has such an awful user interface. It seems to me that Git has become prematurely popular. The features are great but the command-line interface needs a serious redesign.

    I prefer Mercurial due to the friendlier interface, but am afraid it’s falling behind. Hopefully the two products will continue to compete and provide a compatibility layer for speaking to each other’s repositories.

  3. Adrian: thanks for the shortcuts, I like that they are supported by hg!

    berry__: until I met mercurial, I thought I was too stupid to use DVCSes in general. Turns out that actually git just likes to remind me that it’s smarter than I am!

    Martijn: git and hg are functionally pretty equivalent and I hope they stay that way. I really like hg’s interface and I think its simplicity will see it remain popular and approachable for a long time to come.

    • For those considering the move to DVCS, you might want to check out Kiln Harmony which supports simultaneous Mercurial & Git in every repository. You can read about it at blog.fogcreek.com. Kiln Harmony allows anyone to toggle back and forth between Git & Mercurial to see “which fits” them.

  4. Hey! Thanks a lot for this reference and I love the design of this blog. I have the situation where I didn’t tell mercurial to delete some files, and now I’m getting a bang(!) on those files. I don’t want to hg revert and lose the changes I’ve made to current files… I just want mercurial to forget about them. I also cannot do a revert on every file because most of them are entire folders of Node.js modules :-) I could decipher the human genome with pen and paper before I could manually remove each of those files. Any suggestions? Thanks!

  5. I only use CVS, GIT, HG, and SVN to pull source codes from repositories. With GIT, I can check pull the current HEAD from the repository (i.e. git ls-remote URL HEAD) and compare it with mine to see if it is necessary to do a git pull to update my local source from the repository. With SVN, it is a bit trickier (i.e. svn info URL | sed -ne’s/^Revision: //p’). With CVS and HG, I have no idea. However, I sure would like to know how to achieve the same thing with HG. Anyone?

  6. Nice article. Thank you. Just to help avoid confusion, I think your description of “hg update” should be instead under the header of “hg pull”. It’s also worth adding a summary of “hg update”, which we use as a core command all the time here at Target.com.

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

This site uses Akismet to reduce spam. Learn how your comment data is processed.