To start using Mercurial to keep track of a project.
$ hg init $
This creates the repository root in the current directory.
Like CVS5with its CVS directory and Subversion6with its .svn directory, Mercurial keeps its private data in a directory. Mercifully there is only one of these, in the top level of your project. And rather than holding details of where the actual repository is to be found, the .hg directory holds the entire repository.
Next you need to specify the files you want Mercurial to track.
$ echo "There was a gibbon one morning" > pome.txt $ hg add pome.txt $
As you might expect, this marks the files as to be added. And as you might also expect, you need to commit to record the added files in the repository. The commit comment can be supplied on the command line; if you don't supply a comment, you'll be dropped into an editor to provide one.
There is a suggested format for these messages -- a one line summary followed by any more required detail on following lines. By default Mercurial will only display the first line of commit messages when listing changes. In these examples I'll stick to terse messages, and I'll enter them from the command line.
$ hg commit -m "My Pome" -u "Jim Hague <firstname.lastname@example.org>" $
Mercurial records the user making the change as part of the change information. It is usual to give your name and email address as I've done here. You can imagine, though, that constantly having to repeat this is a bit tedious, so you can set a default user name in a configuration file. Mercurial keeps global, user and repository configurations, and it can go in any of those.
As with Subversion, after further edits you see how your working copy differs from the repository.
$ hg status M pome.txt $ hg diff diff -r 33596ef855c1 pome.txt --- a/pome.txt Wed Apr 23 22:36:33 2008 +0100 +++ b/pome.txt Wed Apr 23 22:48:01 2008 +0100 @@ -1,1 +1,2 @@ There was a gibbon one morning There was a gibbon one morning +said "I think I will fly to the moon". $ hg commit -m "A great second line" $
And look through a log of changes.
$ hg log changeset: 1:3d65e7a57890 tag: tip user: Jim Hague <email@example.com> date: Wed Apr 23 22:49:10 2008 +0100 summary: A great second line changeset: 0:33596ef855c1 user: Jim Hague <firstname.lastname@example.org> date: Wed Apr 23 22:36:33 2008 +0100 summary: My Pome $
There are some items here that need an explanation.
The changeset identifier is in fact two identifiers separated by a colon. The first is the sequence number of the changeset in the repository, and is directly comparable to the change number in a Subversion repository. The second is a globally unique identifier for that change. As the change is copied from one repository to another (this is a distributed system, remember, even if we haven't come to that bit yet), its sequence number in any particular repository will change, but the global identifier will always remain the same.
tip is a Mercurial term. It means simply the most recent change.
Want to rename a file?
$ hg mv pome.txt poem.txt $ hg status A poem.txt R pome.txt $ hg commit -m "Rename my file" $(The command to rename a file is actually hg rename, but Mercurial saves Unix-trained fingers from typing embarrassment.)
At this point you may be wondering about directories. hg mkdir perhaps? Well, no. Mercurial only tracks files. To be sure, the directory a file occupies is tracked, but effectively only as a component of the file name. This has the slightly unexpected result that you can't record an empty directory in your repository.7
Given this, and the status output above that suggests strongly that Mercurial treats a rename as a copy followed by a delete, you may be worried that Mercurial won't cope at all well with rearranging your repository. Relax. Mercurial does store the details of the rename as part of the changeset, and copes very well with rearrangements8.
Want to rewind the working copy to a previous revision?
$ hg update -r 1 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $
hg update updates the working files. In this case I'm specifying that I want to go back to local changeset 1. I could also have typed -r 3d65e7a57890, or even -r 3d; when specifying the global change identifier you only need to type enough digits to make it unique.
This is all very well, but it's not exactly distributed, is it?