Mercurial to Git Migration

Wha? You have hg repos?

I was always a fan of Mercurial. It gave me the benefits of git, while also giving me the benefits of absolute order of commits.

While I used git for work (and svn/cvs/p4/etc before that), about 1/3 of my personal repos were using hg.

In fact, that was the primary reason I was hosting many of my repos on BitBucket instead of GitHub. Well, that and they allowed private forks.

If you love it so much, what’s the problem?

Atlassian announced that the were not only ending support for hg, but that they would be deleting all the Mercurial repositories.

Sure, this isn’t the first time my hosting provider has decided to remove all my repos. Queue projectlocker, google code, etc (not to mention voluntarily leaving sites like sourceforge).

I decided to write up this page in case anyone else has to do the migration and wants some tips.

The Migration

I did NOT automated this process… it is very manual.

Tools

I am using Hg-Git Mercurial Plugin to do the conversion. Make sure to have that installed first.

They tell you to install easy_install, but we just use pip now.

Which repos?

The first step is to identify which repositories need to be migrated. You can go to https://bitbucket.org/dashboard/repositories?scm=hg to see a list of your Mercurial repos.

For the rest of this process, I will refer to old repository as “REPO” and the new one as “REPO_v2”. I thought about trying to change it in place, but did not want to risk that they would delete it anyway.

Code migration

Create REPO_v2

Go to https://bitbucket.org/repo/create and create a new repository named REPO_v2. For example, if you are replacing a repository named “MyCoolThing”, create “MyCoolThing_v2”

When creating REPO_v2, I’d recommend looking at the settings of REPO and copying the description.

I’m personally enabling the Issues and Wiki for all the new repositories. I am also NOT adding a README, because I do not want it to conflict with any existing code.

Clone both repos

$ hg clone ssh://hg@bitbucket.org/YOURNAME/REPO
$ git clone git@bitbucket.org:YOURNAME/REPO_v2.git

Convert the hg to git

$ cd REPO
$ hg bookmark -r default master

Now here’s an important part. If you have additional branches, you will have to bookmark each and every one.

Assuming hg bookmark -r source target:

  • source and target can not be the same
  • do not include origin/ in the target name

So if you have an hg branch named “IT-1” for example, you might consider doing something like hg bookmark -r IT-1 hg_IT-1 so that it’s obvious which branches were original.

Once you have bookmarked all your branches, nano .hg/hgrc (or vi or whatever) and change the default path entry.

default = git+ssh://git@bitbucket.org:YOURNAME/REPO_v2.git

Save that, then we do the conversion.

$ hg push

Gotcha

Out of the 29 repos I converted, there was 1 that was problematic. It had 9 years of history and had previously been through multiple VCS systems; which caused a few unsightly artifacts in things like tag names.

To resolve this, I used this at the command line to bookmark the branches:

$ hg heads | grep 'branch:' | sed -e 's/branch:[ ]*//g;s/^/\"/;s/$/\"/;p;s/ /_/g' |  xargs -n2 sh -c 'hg bookmark -r "$0" "hg_$1"'

I know it’s ugly. Here’s what it is doing:

  1. hg heads | grep 'branch:' Grabbing a list of branch names
  2. s/branch:[ ]*//g Removing the word ‘branch: ‘
  3. s/^/\"/;s/$/\"/ Wrapping them in quotes so they count as 1 argument
  4. p;s/ /_/gReturning both the original name AND a copy with spaces replaced with underscores
  5. xargs -n2 Passing both copies to hg bookmark
  6. hg bookmark -r "$0" "hg_$1" Which then prepends the ‘hg_’ to the one without spaces

Verify

$ cd ../REPO_v2
$ git pull

You should see your code and any branches you created.

Verify in your REPO_v2 source online.

Wiki migration

The wiki migration follows the same pattern with one slight gotcha.

Remember how we chose to NOT include the README above? Well, you don’t have the option of not including the Home.md in a default wiki.

If you don’t have a Wiki on your old repository, skip this step.

Clone the repos

$ hg clone ssh://hg@bitbucket.org/YOURNAME/REPO/wiki
$ git clone git@bitbucket.org:YOURNAME/REPO_v2.git/wiki wiki_v2

Note the ` wiki_v2` at the end of the git clone. Without that, the two will conflict.

Do the conversion

$ cd wiki
$ hg bookmark -r default master

nano .hg/hgrc and change the default path entry.

default = git+ssh://git@bitbucket.org:YOURNAME/REPO_v2.git/wiki

Save that, then we do the conversion.

$ hg push

You may have to do some resolution here. For example, in some of my prior wikis, I had replaced Home.md with Home.wiki. To resolve this:

$ hg pull
$ hg merge
$ hg commit
$ hg rm Home.md
$ hg commit
$ hg bookmark -r default master
$ hg push

Whatever you do to resolve the conflicts on your wiki, make sure to re-bookmark before you push again.

Verify

$ cd ../wiki_v2
$ git pull

You should see your prior wiki files.

Verify in your REPO_v2 wiki online.

Issues

Issue migration is thankfully a little easier. Skip this if you do not have any issues in your old repo.

Export old issues

  1. Go to https://bitbucket.org/YOURNAME/REPO/admin/issues/import-export
  2. Look under Export Issues
  3. Click Start Export
  4. When it is finished, download the zip file

Import the issues

  1. Go to https://bitbucket.org/YOURNAME/REPO_v2/admin/issues/import-export
  2. Look under Export Issues
  3. Click Choose File and select your zip file.
  4. Click Start Import.
  5. The UI seems to hang before it is done; but you will get an email telling you that it is complete.
  6. Verify that the issues have been imported.

Cleanup

  1. On the top-left of REPO_v2, right-click on your project name and copy the link address
  2. Open https://bitbucket.org/YOURNAME/REPO/admin
  3. On the Repository Details page, scroll to the bottom
  4. Click on Delete Repository
  5. Paste in the link from REPO_v2. It should look like: https://bitbucket.org/YOUR_NAME/REPO_v2/
  6. Click Delete

Repeat

Do the same process for each repository until there are no Mercurial repositories left.


© 2019. All rights reserved.