Saturday, October 23, 2010

Yet another how to convert an svn repo to git

If you don't have branches in your svn repo then converting to git is an easy task. Just use git svn and you are done. I not only had branches but I also had multiple projects in the same svn repo and didn't want to move all of them to git. So the first step is to use git svn but explicitly specify where the trunk, branches and tags are for the particular project I wanted to move.

git svn clone http://path-to-root-of-svn-repo -A authors.txt -t tags/myproject -b branches/myproject -T trunk/myproject myproject

Notice that under the root of the svn repo, I have trunk, branches and tags folders. Each project has its trunk under trunk/project, its branches under branches/project and its tags under tags/project. The first argument to the command above is the root of the svn repo and trunk, branches and tags of myproject are given as -T, -b and -t parameters. Nothing else worked correctly for my case. Notice also that you need an authors.txt file of the form

username = Firstname Lastname <email>

with all users that have committed in the svn repo. The process will abort if it finds a name that is not in the authors file and you will have to add it and run the command again.

After the command finishes (and it might take a while) we have our git repo under myproject. There is one problem though (actually they are two): All svn tags and branches are now git remote tracking branches. If we just push our git repo to a remote hosting site like github we 'll have only the master branch (previously svn trunk). So we have first to convert all previous svn tags to real git tags and the then push everything (master, branches and tags) to github.

git branch -r
will list all remote tracking branches in the newly created git repo. Those with name of the form tags/tagname are coming from svn tags. As Paul Dowman explains in his post, for each one we have to create a git tag
git tag tagname tags/tagname
and then delete the remote tracking branch
git branch -r -d tags/tagname

The script I wrote to do the conversion is

git branch -r |awk -F "/" '$2 {printf("git tag %s tags/%s\n", $2, $2)}' |sh
git branch -r |awk -F "/" '$2 {printf("git branch -r -d tags/%s\n", $2)}'|sh

After that step we connect the local repo with github
git remote add origin
and push but don't forget --tags otherwise the tags won't be pushed.
git push origin master --tags
and push again with --all to push the branches
git push --all