Until recently, I was a big fan of using Subversion for most of my private projects. Now, however, I'd rather be using Git. This is all well and good for new projects, but how do I move the mature projects from my repository to Git (specifically GitHub)? Turns out, it's actually possible although the known methods aren't very friendly/reliable. Because of this I've written a simple script for converting a Subversion repository to Git, which will pretty much go through the entire process for you - including the migration of branches and tags.

It's written in Shell, and should be compatible with most (if not all) shells. Naturally, the project is called svn-to-git and is available on GitHub. You can download the latest version from the Tags section. Below is a small guide on how to use it; it's extremely simple when used correctly.

Usage Guide:

Firstly, download the latest stable source (or master, if you wish) and extract it. Then just start up the script:

$ cd svn-to-git-v1.0.0/
$ sh svn-to-git.sh

This will start up the script, and you'll be prompted for information as needed (so feel free to go and get on with it, if you wish).

The first things you'll be prompted for are just basic paths, specifically where your SVN repo is and where you wish your Git repo to reside. Enter this information as below:

Welcome to svn-to-git, a simple and effective way to translate SVN to Git.

Please enter your SVN url/path: https://riouxsvn.com/svn/test-repo-zacke/  
Please enter your desired Git directory: ~/GitRepo           

SVN PATH: https://riouxsvn.com/svn/test-repo-zacke  
GIT PATH: /Users/iwhitfield/GitRepo  

Your repository will then be checked out from the place you specify. At this point, you will need to modify the SVN authors to their Git counterparts (if they have them). You will see a prompt like this:

Please edit the following lines to match the correct Git format.  
As an example:

username = username <username>  
username = Isaac Whitfield <[email protected]>

Please type in the command to start up your favourite shell editor below.  
Just press enter if you don't know any:  

This is just an opportunity to select your favourite Terminal editor instead of using the default (nano). You can select from any of the following:

* vi
* cim
* nano
* pico
* emacs

Convert each item in the displayed list to match the format above, and save the file, then exit the editor. If a user doesn't have a GitHub account, just leave their line as-is. You'll then be asked about the layout of your Subversion repository. Select the option which applies to you - this is important as it affects the handling of your repository in the next steps.

Please select your SVN layout:

1. Standard layout (branches/tags/trunk).  
2. Non-standard with branches and tags.  
3. Non-standard without branches and tags.

Please enter your choice:  

Your Git repository will then be created from the Subversion repository and you will be asked for a Git commit message. Enter this and press enter. This will initialize the new repository with a commit, ready to be pushed. It is at this point you will be prompted for a Git remote to add your repo to. Don't worry though, if you don't have one you can simply type "none". If you do have one, just type in the remote URL.

Initialized empty Git repository in /Users/iwhitfield/GitRepo/.git/  
r1 = 299cb53dc694a61bb071f5bc98dc7542e760a134 (refs/remotes/import/trunk)  
Checked out HEAD:  
  https://riouxsvn.com/svn/test-repo-zacke/trunk r1

Please enter the commit message for moving from SVN: Initial import from SVN.

[master 6fd0264] Initial import from SVN.
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore

Please enter your remote URL, if you don't have one, type 'none': [email protected]:iwhitfield/TestRepo.git

Pushing all branches to new origin

Counting objects: 5, done.  
Delta compression using up to 8 threads.  
Compressing objects: 100% (2/2), done.  
Writing objects: 100% (5/5), 474 bytes | 0 bytes/s, done.  
Total 5 (delta 0), reused 0 (delta 0)  
To [email protected]:iwhitfield/TestRepo.git  
 * [new branch]      master -> master

Pushing all tags to new origin

Everything up-to-date

You're done! Here is the state of your Git repo:

* master


And you're finished. Your remote/local Git paths will contain the latest code, in addition to all branches and tags - with a summary of what was migrated printed out (I only had a master branch above). At this point, you should be able to see the changes on your Git repo.

Test Repo Import

If something went wrong, give it another shot - it may just have been something entered incorrectly. The script is surprisingly solid when used alongside the correct parameters. If you have any issues (or suggested improvements), feel free to open one on the GitHub repo, or leave a comment below.