Like many businesses that have grown into software development, Jaguar’s dev tool stack began fairly simple and has grown gradually since then. One of the first things I did upon taking this job was establishing a version control server. Distributed systems like Git were starting to grow in popularity, but for simplicity befitting my own inexperience, I opted to go with the tried-and-true choice, Subversion.
Subversion served us well, but over time, we’ve run into the usual set of issues:
- Merging is messy
- Branches being part of the filesystem is inelegant, ugly clutter
- No offline functionality
- “.svn” folders everywhere, all over the brand new rug
After having gained the experience of a couple years of SVN usage, I decided it was time to look at the new breed of alternatives. Specifically, I wanted to embrace “branchy” development workflows.
We experimented with Mercurial for a while, but we settled on Git. Git performed better with large repos that Mercurial would choke on (at that time, at least), and while Git originally lacked a native Windows port, the C rewrite and msysgit has solved that issue.
That brought us to the problem of this blog post: how to get Subversion repositories into our new Git setup.
Of course, we can always just create a new Git repository, checkout everything from SVN (or, if we’re smart, svn export, so that we don’t get all those darn .svn/ folders), dump it into the newly created Git repo, and call it done. But if we do this, we lose our commit history, we lose branches and tags, and everything else VCS related from the repo’s past SVN life.
The tool we used was svn2git, a Ruby gem that provides a command-line tool for easy conversion of SVN repos to Git repos, bringing all the history and branches along for the ride.
To convert a repo, we simply do:
$ svn2git http://svn.example.com/path/to/repo
The svn2git command by default assumes a standard SVN layout: three subfolders named “trunk”, “branches”, and “tags”.
However, if this is not the case, we can communicate this to svn2git with command line switches:
$ svn2git http://svn.example.com/path/to/repo --trunk trunk --nobranches --notags
And if there are no subfolders at all, but rather the repo is in the root folder itself, there’s a switch for that too:
$ svn2git http://svn.example.com/path/to/repo --rootistrunk
There are even more settings, including the ability to supply passwords or filter out files in the conversion process, which are explained in the svn2git README.
Here at Jaguar, we had two basic repo structures to convert: the standard trunk/branches/tags layout, and the “root is trunk” layout, where the content is all in the root folder and not in any organizational subfolders.
In order to help preserve history, we needed an authors file. This will map SVN usernames to identities as used in Git.
# authors.txt joe = Joe User tom = Tom Selleck
This can either put this file somewhere world-readable and call it with the –authors switch (ie. –authors ~/authors.txt), or it can be stored as ~/.svn2git/authors (no .txt extension) and svn2git will load it automatically.
NOTE: svn2git turns your current working directory into a Git repo containing the files from the SVN repo you’re pulling from. That means you probably want to create an empty directory for your project and change to that directory before running svn2git. Make sure you’re *not* running “git init” – svn2git does this itself, so your directory should not be make into a Git repo ahead of time.
The step-by-step repo conversion process breaks down to this:
1. svn2git checks out into your current directory, so make a new directory for project and change to it
$ mkdir myproject $ cd myproject
2. Run your svn2git command
$ svn2git (svn-path) (svn2git options)
3. Add remote for destination central git repo
$ git remote add origin (git-path)
4. Push to origin/master
$ git push origin master
At the end of Step 2, you will have a fully functional Git repo on your system. If you aren’t trying to move the repo to a remote Git server, you can skip steps 3 and 4. These steps aren’t specific to using svn2git, but are simply what you do in order to get a local Git repo moved over to a remote server.
It has actually been over a year since we used svn2git, but the project remains in active development. svn2git 2.0 appears to have added a feature for actively mirroring SVN repos to Git, as opposed to just doing a one-time conversion.