Migrating from Subversion to Mercurial

2010, Jul 28    

I have been reading about Git and Mercurial everywhere lately, so I wanted to give them a try. I mainly develop on Windows and the tools for Windows are better for Mercurial, so I decided to start with it.

The best way to get a feel for is with real code, so I decided to migrate my Subversion repository to Mercurial.

The first step was to install TortoiseHg, the Windows shell extension for Mercurial. I then read that it is much quicker to work with a local copy of a Subversion repository, so my next step was to pull a copy down from the server.

Sync Subversion to the Local Machine

  1. Create an \scm\svn (source control management) directory to house the local copy of the repository.
      mkdir \scm\svn
  2. Create the local Subversion repository.
      svnadmin create \scm\svn\myrepository
  3. Create an empty hooks\pre-revprop-change.bat file
      echo @ECHO OFF > \scm\svn\myrepository\hooks\pre-revprop-change.bat  
  4. Initialize the local repository for syncing to the remote repository
      svnsync init file:///scm/svn/myrepository http://remote.repository.com/svn/myrepository
  5. Now run the sync.
      svnsync sync file:///scm/svn/myrepository

The last command pulls in all the revisions from the remote repository one at a time until it mirrors all of the changesets. Once this is done, you have a fully functional local copy of the SVN repository to work with.

Configure TortoiseHg

At a minimum, you should set your username and enable the convert extension. To do this, in Explorer, right click and select TortoiseHg | Global Settings. Set your username in the Commit section to your name/email in the format First Last <youremail@domain.com>. Next go to the Extensions section and make sure the Convert extension is enabled.


Do the Initial Convert of the Repository

I then did a trial run of converting the local SVN repository to an Hg repository.

  1. Create an \scm\hg directory to house the Mercurial repository.
      mkdir \scm\hg
  2. Create the Mercurial repository to import the SVN repository into.
      hg init \scm\hg\myrepository
  3. Run the conversion.
      hg convert -s svn \scm\svn\myrepository \scm\hg\myrepository

Cleaning up the Conversion

Looking through the history of my newly imported repository, I noticed that my username changed over time depending on the Linux user account I was working with at the time. It would be nice to change all of these to the preferred mercurial format. Luckily, that is pretty easy, hg convert can use a file to map SVN usernames to Hg users. To do that, create a file called authors.txt with conversions like the following;

robprouse = Rob Prouse <rob@email.com>
rprouse = Rob Prouse <rob@email.com>
jdoe = John Doe <john@doe.com>

My repository is also a bit of a mess. It started out as a CVS repository years ago which was later migrated to SVN. Over the years, every project I worked on was filed away in there. One thing about Mercurial, is that it is best to have one project per repository since you can only clone the whole thing. To do this, I created a filemap.txt file and used it to pull out each project into its own repository.

include /projects/Project1/
include /projects/Project1.Tests/

For more information, check out the documentation. I then reran the conversion that I did above, except I pull now from my newly converted Hg repository and I used the author and file map files. I updated the filemap.txt for each project that I wanted to export and re-ran the conversion.

hg init \scm\hg\project1
hg convert --authors authors.txt --filemap filemap.txt -s hg \scm\hg\myrepository \scm\hg\project1