Converting from Subversion to Mercurial

Here, I will be posting notes on converting Subversion repositories to Mercurial.

NOTE: This is work in progress. I will probably come back and change things as well as adding.

Some links on using Mercurial:
Hg Init: a Mercurial tutorial by Joel Spolsky
QuickStart in the Mercurial Wiki

I have got TortoiseSVN 1.8.3 including the command line clients and TortoiseHG 2.10.1 installed.

There are several short tutorials on converting from svn to hg. They all suggest that you first create a local copy of your subversion repository to work on.

A – Create a local copy of your subversion repository
Creating this local copy can easily be done as described by Massimo Iacolare, which I used as a guide.

1 – Create a local svn repository
You can use any local directory as the path to your local svn repository, I will be using the extension .svn to remind me that it is a svn repository. The converted Mercurial repository will not get an extension.

Unfortunately there is the first gotcha: Massimo seemed to be using an older version of svn that used db format 4. The current svn 1.8 uses db format 6 by default, and as Jeroen W. Pluimers found out, the current Mercurial does not support it yet. So, what can we do until the Mercurial developers fix this problem? Why, use db format 4, of course:

svnadmin create --compatible-version 1.7 [path\to\your\new\repository.svn]

I am not sure whether the steps 2 to 4 are necessary, it seemed to work fine without them. I’ll keep them here just in case I run into trouble later because I left them out.

2 – Enable writing on your new repository
Open the file [path\to\your\new\repository.svn]\conf\svnserve.conf and uncomment the line

[general]
password-db = passwd

This tells SVN which file stores the user credentials.

3 – Add a new user
Open the file [path\to\your\new\repository.svn]\conf\passwd and add a new user:

[users]
svnsync_user = svnsync

4 – Give your new user read/write permissions
Open the file [path\to\your\new\repository.svn]\conf\authz and add:

[/]
svnsync_user = rw

5 – Enable rev propchange (revision property change)
create a text file pre-revprop-change.bat in [path\to\your\new\repository.svn]\hooks containing:

exit 0

This can be done easily with

echo exit 0 > [path\to\your\new\repository.svn]\hooks\pre-revprop-change.bat

6 – Initialize the repository

svnsync init file:///[path/to/your/new/repository.svn] [REMOTE PATH]

Getting the local repository path right can be tricky. Pay close attention to the number of slashes and use forward slashes. e.g.

svnsync init file:///c:/some/path/here.svn https://svn.somesvnserver.com/svn/repository

7 – Synchronize
Once the repository is initialized, you can synchronize it as often as you like:

svnsync sync file:///[path/to/your/new/repository.svn]

Be aware, if your repository is big, the first synchronization may take very long.
After the synchronization has been done once, you can keep it in sync by just repeating step 7.

B – convert your local Subversion repository to a Mercurial repository

This is a one step action:

hg convert [path/to/your/new/repository.svn] [path/to/your/hg/repository]

If you omit the second parameter, hg convert will assume [path/to/your/new/repository.svn-hg] which is probably not what you want, but you can easily rename the directory later on.

The above converts the whole svn repository, including any branches to a single Mercurial repository, as this command shows:

hg branches -a

(You must execute it inside the repository.)
This will also list the pseudo branch “default” which corresponds to the “trunk” in svn.

You can also specify any path within the svn repository to convert, e.g. only the trunk:

hg convert file:///[path/to/your/new/repository.svn]/trunk [path/to/your/hg/repository]

Alternatively, you can convert the whole repository and clone it for every branch to a new Mercurial repository, like this:

hg clone -r [branchname] [path/to/your/hg/repository] [path/to/your/hg/branch]

Due to different concepts of users in svn and Mercurial (one uses names, the other uses email adresses), you can provide a mapping file for users to emails. It must contain one line per user like this:

arist = Aristotle <aristotle@phil.example.gr>
soc = Socrates <socrates@phil.example.gr>

(This example is taken from Mercurial: The Definitive Guideby Bryan O’Sullivan)
And you pass it to the conversion with the –authors option.