Over the last few days I've converted some Subversion repositories used for Debian packaging to Git. None of these Subversion repositories contained upstream sources because of Subversion's storage inefficiency. With Git I wanted to change that and also track upstream sources in my repositories. To move a Git repository from a debian-only to debian+upstream layout I found zack's recipe very helpful.

The actual conversion to Git was done with git-svn. I cloned the Subversion repositories with git-svn's --prefix=svn-import/ and --stdlayout options so that the trunk and all branches and tags were imported as remote branches with svn-import/ prepended. Then I created local branches of the previous Subversion branches and removed the remote remnants, for example:

git checkout -b debian/backports/etch svn-import/branches/etch-backports
git branch -d -r svn-import/branches/etch-backports

The Subversion tags are imported as svn-import/tags/<version> where <version> is the Debian version number. I don't need branches for every version of my packages but I wanted to convert these tags to real Git tags but without losing the actual commit dates and messages. To achieve this I wrote this small script:

#!/bin/bash

for branch in `git branch -r`; do
    if [ `echo $branch | egrep "svn-import/tags/.+$"` ]; then
        version=`basename $branch`
        subject=`git log -1 --pretty=format:"%s" $branch`
        export GIT_COMMITTER_DATE=`git log -1 --pretty=format:"%ci" $branch`

        echo "Tag $version [Y/n]?"
        read yesno
        if [ -z $yesno ] || [ $yesno = "Y" ]; then
            git tag -s -f -m "$subject" "debian/$version" "$branch^"
            git branch -d -r $branch
        fi
    fi
done

For each remote branch that contains svn-import/tags/ it gets the version number, the commit message of the tag and exports GIT_COMMITTER_DATE (man git-tag) with the value of the date the version was tagged in Subversion and then asks you if it should tag the parent of the tag branch with the original commit date and message and remove the then unnecessary tag branch. The "safety measure" is there because people sometimes commit directly to Subversion tags (ugh!) and then "$branch^" would not be the commit you want to tag. To decide which Subversion tags are safe to tag with this script, gitk --all can be of great help.