In a previous post, I detailed how we converted Subversion repositories into Git repositories.

As I mentioned in that post, we also used Mercurial before moving to Git. In the interest of consolidating everything to one VCS, we needed to convert these as well.

We came across a mention on the Git wiki to a tool called hg-to-git, which, by all appearances, has only been released to the world in the form of a mailing list post: Mercurial to git coverter.

We didn’t anticipate much success with this years-old tool copy-pasted to the mailing list, so we turned our efforts elsewhere.

Most blog posts out there suggest using fast-export. These posts included:

At the time, when we tried running fast-export (on OS X as well as Linux), it invariably failed and spat out an error:

AttributeError: 'httprepository' object has no attribute 'branchtags'

Interestingly, searching Google for this error yielded just one hit, a Github issue, which went unresolved. However, this issue did close with the recommendation to move on to a newer tool, a Mercurial extension called hg-git, which is where we headed next.

Spoiler alert – hg-git is where we finally achieved success.

Installation

The following are the exact steps we took to use hg-git, on a machine running Ubuntu 10.10:

1. Install dependencies

Ensure setuptools and the Python 2.6 header files are installed:

$ sudo aptitude install python-setuptools python2.6-dev

2. Install hg-git

Install hg-git with setuptools

$ sudo easy_install hg-git

3. Enable hg-git as a Mercurial extension

Edit ~/.hgrc and add the lines:

[extensions]
hgext.bookmarks =
hggit =

You can confirm that it is installed correctly by running “hg help” and looking underneath “enabled extensions:” You should see “bookmarks” and “hggit”

Conversion

Converting a repo to Git involves:

1. Create a Git repository to push to

We were using Gitosis to manage our Git installation, so the first step was to create a new repo in gitosis.conf. The details of setting up a Git repo are beyond the scope of this article – if you’re doing this, I assume you have a working Git installation or are using a hosted service, and already know how to generate a new remote repo.

2. Checking out the Mercurial repository

$ hg clone http://path-to-your-repo

3. Make a bookmark to tell Git which branch is “master”

The main branch of a Git repository is called “master”. This isn’t true of Mercurial. So, for the import, we need to add a bookmark of the name “master”, which hg-git will use to identify what the Git “master” branch should be.

In most cases, this will be the Hg default branch, “default”.

$ hg bookmark -r default master

Note: in the case of one Hg repo which had originally been a Subversion repo itself, there was no “default” branch. Instead, the branch name “trunk” had been preserved in whatever conversion process we had done originally. So in that case, we ran…

$ hg bookmark -r trunk master

… which let Git know that “trunk” is what should be made into the master branch

4. Run the push command

$ hg push git+ssh://(git repo location)

Note the git+ssh:// prefix. Normally when using git push over ssh, we just use user@hostname:repo-name.git, and the git+ssh is implied. For the “hg push” command, however, it was necessary to state it explicitly.

And that’s it. Once the push completes, the remote Git repo has everything it needs, and can be interacted with purely through Git from then on.

It was pretty impressive to see a repository get converted from Subversion to Mercurial to Git and maintain its history, branches and tags. We’re happy Git users now, and I’m thankful for how smooth both svn2git and hg-git made that transition.