An Open Access Peon

12 September 2012

Migrating svn to git with sub-directories

On EPrints we have a slightly odd layout in our svn repository:


This works well enough with svn where you can checkout a sub-directory but git only allows you to check out the entire repository - branches are real branches rather than just named directories. The correct git usage is to use separate repositories for "docs", "extensions" and "system" and place the contents for each one at the repository root.

The goal of the migration to git is therefore to move trunk/system up to trunk/, branches/3.3/system up to branches/3.3 and so on for branches still in use. (For my own sanity I'm going to ignore tags.)

One approach might be to "git svn clone" the entire svn tree and then move the elements of system/* up a directory. The downside to this approach is every file in the repository will then be touched with that movement, losing the ability to (trivially) see the last time a file was modified.

I also tried use the svn svn-dump-reloc tool to move directory contents up into their parent. That drove me down a path of despair of broken historical file movements and duplicated directory creations (because moving system/trunk/ to trunk/ duplicates the initial trunk/ creation).

The eventual approach taken was to use git-svn's ability to clone a sub-directory and magically place it in the root of the new git repository. I started with trunk/:

git svn clone -A users.txt eprints

And the same with the 3.3 branch:

git svn clone -A users.txt 3.3

I can then create an empty branch for 3.3 (kudos to in my git trunk clone:

cd eprints
git checkout --orphan 3.3
git rm -rf .

git can pull in the content of a remote repository like so:

git remote add -f 3.3 ../3.3/
git merge -s ours 3.3/master

Tidying up:

git remote rm 3.3
git checkout master

This repository can then be pushed up to github using their standard instructions:

git remote add origin
git push -u origin master

And to push the branch(es):

git push origin 3.3