Mercurial is a modern, open-source, distributed version control system. You may have heard of git, which is somewhat more popular today; git and Mercurial are very comparable and offer mostly similar functionality.
Developers use Mercurial to keep track of changes to the source code of their applications. It can be used to keep track of changes to any directory of files, although, like most source control systems, it does best when those files are text files (as opposed to binary files). Mercurial also allows multiple developers to work on the same directory of source code simultaneously, and it manages the process of keeping track of each developer’s changes and then merging those changes.
Mercurial follows a time-based release plan and publishes a major release every three months, in February, May, August, and November. A minor release is published each remaining month. Note that Mercurial does not use sematic versioning, therefore there is no significant difference between 2.9.2 (the last of the 2.9 releases) and 3.0.
Backwards-compatibility is a critical requirement for Mercurial, therefore it’s generally safe to simply upgrade your Mercurial installations as needed. It’s a good idea however to do so at least once every three months, as some features can render old clients unable to operate on newer repositories.
A selection of noteworthy versions:
|3.5||Drops support for Python 2.4 and 2.5||2015-07-31|
|2.1||Introduces changeset "phases" enabling safe history modification||2012-02-01|
|1.9||Introduces a Command Server API to support better application integration||2011-07-01|
|1.7||New repository format supports uncommon filenames||2010-11-01|
Installation and Setup
You can download Mercurial from the project’s website, and there are graphical utilities for Windows, Linux and OSX if you’d prefer that to a command line interface. Most Unix package managers include Mercurial, for example on Debian/Ubuntu:
$ apt-get install mercurial
You can verify Mercurial is installed by running:
$ hg --version
Mercurial works out of the box, but you’ll likely want to configure Mercurial to know who you are before you go further. To associate a username with your commits edit
mercurial.ini in your home directory on Windows) and add the following lines:
[ui] username = Your Name <firstname.lastname@example.org>
If you don’t want to do this you can always specify a username when you commit with the
-u flag, e.g.:
$ hg commit -u "Your Name <email@example.com>"
See also the Mercurial Tutorial
Creating a Mercurial Repository
A Mercurial repository is simply a directory (referred to as the “working directory”) containing an
.hg directory with metadata about the contents of the repository. This makes Mercurial very lightweight and easy to start using. To create a new repository simply run:
$ hg init project
project is the name of the directory you’d like to create. This creates a
project directory along with a
project/.hg directory containing the repository itself.
$ cd project $ echo Hello World > hello.txt $ hg stat ? hello.txt
We just created a
hello.txt file in the repository and ran
hg status (or
stat for short) to see the current status of our repository. As you can see
hello.txt is annotated with a
?, meaning Mercurial isn’t yet aware of it. The
add command registers this new file with Mercurial so it will be included in the next commit.
$ hg add hello.txt
Now that Mercurial is aware of a changed file you can run
diff to see exactly what’s changed since the last commit - in this case we’re adding the full contents of
$ hg diff diff -r 000000000000 hello.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hello.txt Sat Jul 23 01:38:44 2016 -0400 @@ -0,0 +1,1 @@ +Hello
And once we’re happy with them and ready to check in our changes we can run
$ hg commit -m "Created a hello world file."
Note that we included a commit message with
-m - if you don’t specify
-m Mercurial will launch a text editor you can enter a commit message in. This is useful if you’d like to provide a longer multi-line message.
Once you’ve committed your changes they no longer show up if you run
hg stat since the repository is now in sync with the contents of the working directory. You can run
log to see a list of commits, and
-v includes additional details like the files each commit touched:
$ hg log -v changeset: 0:b4c06cc77a42 tag: tip user: Michael Diamond@Aodh <firstname.lastname@example.org> date: Sat Jul 23 01:44:23 2016 -0400 files: hello.txt description: Created a hello world file.
Pushing and Pulling
To copy a remote repository to your local disk you “clone” it. To do so simply pass the remote URL you’d like to clone from. To clone the Mercurial source code simply run:
$ hg clone https://selenic.com/hg
This creates a local
hg directory containing a copy of the Mercurial repository you can build, edit, and commit to (though you can’t publish your commits back to the parent repository).
Once you have a repository checked out, you’ll want to keep it in sync as others publish changes to it. You can pull down new changes by simply running:
$ hg pull
This pulls in new commits but doesn’t update your working directory, so you won’t see any changes immediately. To update the contents of the working directory run:
$ hg up
Which updates your working directory to the tip (most recent) revision in the repository.
You can also run:
$ hg pull -u
To pull in new changes and update the working directory in one step.
Assuming you have write-access to the remote repository you can publish any commits you’ve made locally to the remote repository just as easily with:
$ hg push
This uploads your changes as long as there haven’t been any other commits since the last time you pulled. If your
push is rejected because it would “create additional heads” that means you need to pull in those new changes and merge them with your own.
$ hg pull $ hg merge # this creates a new changeset merging your changes with the remote changes $ hg commit -m "Merged in remote changes" $ hg push
Most of the time this is all you’ll have to do since Mercurial handles merging your changes automatically, however sometimes you’ll need to resolve merge conflicts manually (see merging topic). If you need to you can always cancel a merge and get back to a clean working directory with:
$ hg up -c
But remember this is a destructive operation; any changes in the working directory will be erased.
When we’re first starting our work, we have to decide if this is a separate area of work we’re working on, or is this part of an existing line of work. If it’s existing, we can work off of that branch. If it’s new, we’ll start a new branch.
Our workflow then is:
hg branch MyNewFeature
- work work work
hg commit -m "committing my changes"
- work work work
hg commit -m "more changes"
At this point, we want to push our work up to the remote server. But before pushing the changes (ignore this if it is a new branch you haven’t pushed before), we need to check if there are any incoming change to this branch. We can check this with:
hg incoming -b .
If there are any incoming changesets on our branch, we need to do a pull and rebase our changes to the top of the list of changes.
hg pull -b . --rebase
Once this is done or if there are no incoming changesets, we can proceed with the Push.
We only ever want to push our current work, not everything we’ve ever done. I really never push my entire repository, but my current line of work. The reasoning is that pushing the entire repository assumes I’m integrating multiple lines of work. But I only want to integrate my current line of work, and I only want to work in one line at a time.
If this is the first time I’m pushing this branch:
hg push -b . --new-branch
If I’ve already pushed this branch:
hg push -b .
The “-b .” command means just push the current branch, and not anything else.
To change between the working branches:
hg update myBranchName