Migrating from SVN to Git
I’ve migrated several projects from SVN to Git in the last couple of weeks. In doing so I’ve worked out a little process that has seen me right in preserving all of the history. This process relies on the git-svn tool, which you may need to install as a separate package.
1) Create an authors.txt file. This is a file that maps the SVN usernames to the more verbose Git author names. I suggest starting with an empty file and adding to as errors crop up due to missing authors during the import. Alternatively you may be more organised.
Your authors.txt file will look something like this:
username = Full Name <email@example.com>
username2 = Full Name <email@example.com>
2) Import the SVN repository into a new Git repository. Note that this command references the authors.txt file you created in step 1, it includes the username (if any) you require to access the SVN repository, the URL to the repository and the directory to create the new Git repository in. This also assumes that you use a standard trunk, branches, tags layout (if not, omit the -s), and that your URL will be the root of the repository (ie. the directory containing trunk). At any stage consider typing “git svn help” to get assistance.
git svn -s --authors-file=authors.txt --prefix=svn/ --username=svn_username \
clone https://url/path/to/svn/repo/ directory-for-git-repo
This process will take a while. It will fail with an error if it encounters a username that isn’t in your authors.txt file. Add the author and then re-run the command; it will continue from where it left off.
Once it’s complete, consider running it again just in case. My first attempt said it was finished and it wasn’t.
You now have a working Git repository. The SVN repository is hooked up as a remote and all of its branches and tags are prefixed with svn/, which makes them easy to find. The next step is to turn the SVN branches and tags into local Git branches and tags to complete the import.
3) Make local branches for each remote SVN branch. When we do the import we specify that all of the SVN branches go into the prefix svn/. I wrote a brief shell script to perform this step; all it does is to list the remote svn branches (omitting the tags and trunk), and then checkout each one-at-a-time to a local branch.
cd directory-for-git-repo
for i in `git branch -r --no-color | grep 'svn/' | grep -v 'svn/tags/' | grep -v 'svn/trunk' `
do echo $i
git checkout -b `echo $i | sed -e 's|svn/||'` $i
done
4) Make local tags for each remote SVN tag. SVN tags are imported as remote branches, so as for the branches, we run a short script to create local Git tags for each SVN tag.
for i in `git branch -r --no-color | grep 'svn/tags/' | sed -e 's|svn/tags/||'`
do echo $i
git checkout -b tag_branch svn/tags/$i
git checkout master
git tag `echo $i | sed -e 's|svn/||'` tag_branch
git branch -D tag_branch
done
5) Make the master branch from the SVN trunk. I found that my master branch was a superset of every other branch after the git svn import, so in this step we rename the existing master branch, create a new one, and then delete the old one.
git branch -m master oldmaster
git checkout -b master svn/trunk
git branch -D oldmaster
And that completes my import process. The next step is probably to clone the repository, or possibly to push it to its new host. Cloning gets rid of all of the git svn configuration and remote branches and leaves you with a clean Git repository.