Sunday, January 23, 2011

Mercurial in Five Commands

Completing any sort of significant programming project can be nearly impossible without version control. For a class project, I recently collaborated with a small group on a large programming assignment. To keep all of our changes in sync while working miles away from each other, we used a centralized version control system.

Since I've been working quite a bit with Mercurial lately, we went with a free private project on bitbucket. It was the first time my teammates had used Mercurial so I gave a crash course that I thought would be helpful for others as well. A distributed version control system has a large number of commands and features, but 90% of the time, you're just dealing with the basics. When working with a team you can get by with just these five Mercurial commands: clone, commit, push, pull, and update.

Setting up the Project


As I mentioned, we were using a hosted repository on bitbucket, so getting a working copy of the repository on our machines started with each of us executing hg clone. It looked a little something like this:
hg clone https://your-username@bitbucket.org/your-username/project
This will create a local repository with a copy of each file and you're now free to make changes. You can edit files locally and Mercurial will track the changes for you. If you want to add new files or remove existing files, make sure to use hg add and hg remove. (Bonus commands!). Once you're happy with your changes and you want to gather them up in a logical unit it's time for:

Local Snapshots


To save a set of changes locally, you use hg commit. Be sure to write an informative description of this change set since you and others will want to remember what this set of changes was all about. There are a few arguments to the commit command that come in handy, often I do:
hg ci -u your-username -m 'Reduces codebase entropy. All tests pass!'
For more options on the commit command and any other Mercurial command you can use hg help <command>. You can also see a diff of your current files compared to the most recent snapshot using the hg diff command. (Bonus times two!)

Pinning your changes locally is a fantastic feature of distributed version control systems. As I work I tend to take a local snapshot several times an hour. These revisions just exist in your local copy, so you don't need to worry about clashing with other people's code at this point or making sure that all changes are usable. Sometimes when I decide I've gone down the wrong path I'll take a snapshot of the ill conceived changes before I roll them back, just in case I decide later on that some of the ideas weren't so bad after all.

Once you have something that's ready for others to use, it's time to:

Share


To get your changes into the hands of others, you can push them back up to the central repository. You do this with the hg push command. Since we created our local repository using clone, your local copy knows where to send the changes. Also, if you'd like to do something different, like push your changes to a different location than where we cloned from, you can take a look at more options of the push command using hg help push.

The push command will upload all of your local commits, along with those handy descriptions, for the rest of your team to see.

Now others on your team are pushing up their changes too and it would be great to get their changes so you are all working on the same code. What's that saying, "It's better to give than to...?"

Receive


To get the changes others have posted to the repository into your local copy, you use hg pull. Running this command copies the change sets that you haven't received yet to your local repository, but it doesn't edit your files or apply the changes just yet. Since you might want to be selective about what changes you apply, Mercurial splits applying the changes into two steps. First you pull, then you use hg update. When called with no additional arguments like that, hg update applies all of the changes.

I recommend pulling and updating often. In our group, since there were just a few of us, we'd post in a chat room when we pushed changes so others would know to pull. If you push before you pull in other people's changes, you might need to use hg merge. Also, you can see all of the changes which are in your repository with the hg log command. (Triple bonus, hey a hat-trick!)

There you have it!

Want more?


I tried to keep this simple and focused, the bare minimum to work on a project with a small team. Mercurial has more to offer. I haven't touched branches yet, or looking at diffs, or creating your own local repository from scratch, or sharing your changes by running your own server locally. All of these are just single commands! For further reading take a look at Mercurial: The Definitive Guide.

There are a few services which offer hosting of Mercurial repositories. For open source, Project Hosting on Google Code is an option as well as bitbucket which I used for the first time this past week. Any other Mercurial hosting providers that you recommend?