Migrate subversion to Git

Converting existing subversion repositories to Git using git svn is a nice and simple way, but there are a couple of things that I fournd out doing it that was not totally clear.

Requirements

  • Unix bash shell (I will get back to this one)
  • Git installed

Gotcha's

I first started migrating the repositories using my Windows machine, that seems to work for a long time until it fails. Since one migration can take a long time, it can take days before it fails. After using google to find a solution to that, the only recommindation I found was to use linux box or a Mac to migrate.

Now it's time to migrate

Lets say the subversion repository strukture looks like below:

svn://path.to.svn/Project1/Trunk
svn://path.to.svn/Project1/Branches
svn://path.to.svn/Project1/Tags

On the machine that should do the migration, follow these steps:

#> mkdir Project1
#> cd Project1
#> git svn init -t Tags -b Branches -T Trunk svn://path.to.svn/Project1 --prefix=svn/ --no-metadata
#> git svn fetch

This is the part that may take a long time. It fetches through all the revisions in the subversion repository. I am used to start this process and when it is finished, telling other people working on the repository to commit all their changes. Then do git svn fetch. The second time it just fetches the newest changes.

Push the migrated repository to a git bare repo

#> git init --bare ~/new-bare.git
#> cd ~/new-bare.git
#> git symbolic-ref HEAD refs/heads/trunk

#> cd ~/temp
#> git remote add bare ~/new-bare.git
#> git config remote.bare.push 'refs/remotes/*:refs/heads/*'
#> git push bare

Then it is time to rename the trunk branch to master.

cd ~/new-bare.git
git branch -m trunk master

Fixing branches and tags

Since branches and tags are different in subversion and git, it is needed to do some scripting to convert the tags to git tags. Initially, all tags from subversion are getting into the git repository as branches.

cd ~/new-bare.git
git for-each-ref --format='%(refname)' refs/heads/tags |
cut -d / -f 4 |
while read ref
do
  git tag "$ref" "refs/heads/tags/$ref";
  git branch -D "tags/$ref";
done

Move bare repo to a central repository

Up until now, all have been done in a local git repository. It is not useful at all to transfer a subversion repository just down to a local git repo. It needs to be pushed up to a remote repository as well. First thing to do is to add the git remote.

git remote add origin <url to git repository>

Then it is time to push all the branches and tags to the remote repository.

git push --all
git push --tags

The first command here will push all the branches that is in the local git repositories to the remote. Then it is time to push the tags with the second command.

Is it anything else that I did not cover?

And yes it is. It is probably at lot more that can be done when moveing a repository from subversion to git, but this is exactly what I needed when I had to do this kind of work.

One thing that comes to mind is that it is possible to have a mapping file of authors when migrating from svn to git. What that file should contain then is a mapping from subversion username to username in git. Then it is possible to have one tracking on the users history completly. When I did the migration, the most important thing was to get the complete history and who did what in the code and that one users change did not showed up as two users was not important.

--authors-file=<filename>
Syntax is compatible with the file used by git cvsimport but an empty email address can be supplied with <>:

	loginname = Joe User <user@example.com>
If this option is specified and git svn encounters an SVN committer name that does not exist in the authors-file, git svn will abort operation. The user will then have to add the appropriate entry. Re-running the previous git svn command after the authors-file is modified should continue operation. [Git Docs](https://git-scm.com/docs/git-svn)

Links

Teis Lindemark

Read more posts by this author.