Repository setup

To convert from the svn repository, first setup the git repository on the alioth servers as described at Games/VCS/git. Afterwards, do the following on your local machine.

git svn clone --no-metadata \
    svn:// \
    -T /trunk/<package> \
    --branches /branches/<package> \
    --tags /tags/<package> \

Repository Setup notes

Turn the 'tags' branches into git tags

This was copied from pkg-java's migrate-svn-repo-to-git

echo "Converting branches to tags..."
for branch in `git branch -r`; do
    if [ `echo $branch | egrep "tags/.+$"` ]; then
        version=`basename $branch`
        subject=`git log -1 --pretty=format:"%s" $branch`
        GIT_COMMITTER_DATE=`git log -1 --pretty=format:"%ci" $branch` \
            git tag -f -m "$subject" "debian/$(sanitize_version "$version")" "$branch^"
        git branch -d -r $branch

# Remove the remotes/origin/trunk reference
git branch -rd origin/trunk

Merge svn branches

Now merge the branches from svn into the master branch.

$ git merge \
      $(find .git/refs/remotes -type f ! -regex '.*trunk$' ! -regex '.*trunk@[0-9]*$' \
      ! -regex '.*\/alioth\/.*' -print0 | \
      xargs -0 -r echo | sed 's|\.git/refs/||g')

Import orig source

After fetching from the svn repository, it's now time to import the contents of the orig source.

$ git symbolic-ref HEAD refs/heads/upstream
$ git rm --cached -r .
$ git commit --allow-empty -m 'initial upstream branch'
$ git checkout -f master
$ git merge upstream
$ gbp import-orig --pristine-tar <path_to_orig_tarball>

Note: Using the --pristine-tar option is optional.

It is also possible (but optional) to import the upstream history to mimic the git-buildpackage setup, using these two snipets. First import the upstream tarballs matching "origUrl" and rebase the master branch onto it (this need to be done manually for every upstream tarball to be imported, to check everything is working fine):

commit=$(git log -1 --grep="origUrl" --format="%H" --reverse)
message=`git log -1 --format="%s" $commit`
echo "Merging $commit: $message"
version=`echo $message| sed 's/[a-zA-Z_ ]*//'`
echo $version
while [ ! -f ../pkg-games/tarballs/$package_$version.orig.tar.gz ] && read -p "File not found. Version?" version;
        echo "Looking..."
echo "Tarball $version found"   
gbp import-orig --pristine-tar --no-merge --no-interactive ../pkg-games/tarballs/$package_$version.orig.tar.gz
git checkout $commit^1
git merge upstream/$version --allow-unrelated-histories -m "Merge tag upstream/$version"
merge_commit=`git log -1 --pretty=format:"%H"`
git rebase -m --keep-empty -i --committer-date-is-author-date --onto $merge_commit $commit master

Then move the tags to the new master branch:

for tag in $(git tag -l 'debian/*')
        old_commit=`git log -1 --pretty=format:"%H" $tag`
        old_message=`git log -1 --pretty=format:"%s" $tag`
        echo $old_message
        for new_commit in $(git log --pretty="%H" --grep="$old_message" master)
                new_date=`git log -1 --pretty="%ad" $new_commit`
                old_date=`git log -1 --pretty="%ad" $old_commit`
                echo $old_date $new_date
                if [ "$new_date" = "$old_date" ]; then
                        echo "Found $new_commit"
                        GIT_COMMITTER_DATE=`git log -1 --pretty=format:"%ci" $tag` \
                                git tag -f "$tag" $new_commit

Push changes

After this step, push the contents of your local repository.

$ git remote add alioth git+ssh://<username><package>.git
$ git push alioth master
$ git push alioth upstream
$ git push alioth pristine-tar
$ git push alioth --tags

Note: Using a 'pristine-tar' branch is created only if you used the --pristine-tar option above.

This step here is a way to push the tags and branches that were imported from svn (an explanation about this is below). Do this to push all tags and branches that were imported.

$ for REMOTES in `find .git/refs/remotes -type f ! -regex '.*trunk$' \
      ! -regex '.*trunk@[0-9]*$' ! -regex '.*\/alioth\/.*'`; \
      do git push alioth $(echo $REMOTES | sed 's|\.git/refs/||'); done

Editing note : Why perform this last step? git-svn will have created branches for every SVN branch, even deleted ones. Should deleted/abandoned branches always be merged?

Once you have pushed all changes to the shared repository, move the packaging directory from trunk in svn so that no one continues to work on it there.

Move old packaging directory to attic

Move the packaging directory in trunk to the attic section and leave an appropriate message.

$ svn mv svn+ssh://<package> \
      svn+ssh://<package>-svn-save \
      -m "Moving <package> from trunk to attic. Please use git repository instead."

Update .mrconfig

And, finally, add a new section for the new repo in the .mrconfig file from from our SVN trunk:

$ (echo "[<package>]" ; \
echo "checkout = git clone git://<package>.git"; \
echo) >> /path/to/the/SVN/trunk/checkout/.mrconfig
$ svn ci -m "Add <package>'s git repo to the .mrconfig file" /path/to/the/SVN/trunk/checkout/.mrconfig

Cloning and pulling

Anyone pulling from a converted repository will have two steps to perform. The first step is the usual cloning.

$ git clone git+ssh://<username><package>.git

And then the next step involves pulling the "remotes" branches and tags that were pushed.

$ cd <package>
$ git pull origin +refs/remotes/*:refs/remotes/*

Note about tags and branches

Tags and branches are preserved using what's called "git remotes". This means that there are no real git tags and branches visible, but that the SVN trunk, tags and branches are tracked as separate repositories. Downside is that you need to switch to to the remotes individually before you can update them.

All tags and branches are listed under .git/refs/remotes/ and can be checked out, but it is somewhat confusing as all old schemes for using tags and branches are there too...

So to checkout a branch do the following.

$ git checkout remotes/<some_branch>

And for tags.

$ git checkout remotes/tags/<some_tag>


Removing SVN metadata

If you do not initially use --no-metadata (perhaps you want to track the SVN repository for a while, or want to leave it in whilst you debug something) you can remove it later with

$ git filter-branch -f --msg-filter 'sed -e "/^git-svn-id:/d"'

You should not do this for a published repository. See the git-filter-branch(1) man page for more information. In particular for large histories the -d argument might be useful.