Fixing moved subversion repositories when using git-svn

This is mostly for my own later reference, and in case anybody finds this of use.

The instructions are based off ones I found here and here, and are simply modified for people who are using the noMetadata option for git-svn. This is useful for one-shot importing from svn to git.

Suppose that the files were moved in revision 100.

  1. Fetch all of the unfetched svn revisions up to the point where the move occurred

     git svn init http://svn.example.com/svn --trunk trunk
     git svn fetch --authors-file "$AUTHORS" -r 1:100
  2. git-svn init to the path of the trunk/tags/branches on a new svn remote

     git svn init http://svn.example.com/svn -R tmp --trunk project/trunk
  3. Edit the .git/config file and replace refs/remotes/git-svn with refs/remotes/tmp-map in the "tmp" svn-remote

  4. Fetch the initial revision after the move

     git svn fetch --authors-file "$AUTHORS" -r 100 tmp-map
  5. Update the old trunk

     git update-ref $(git rev-parse trunk) $(git rev-parse tmp-map)
  6. This is the tricky part if you're using noMetadata; you have to manually edit the git-svn revision db file, you can't remove it and have it get regenerated (since git-svn doesn't store the id's directly in the commits). The binary format is documented here. Here's a Python script that may help:

     #!/usr/bin/python
     import subprocess, binascii, struct
     dbfile = '.git/svn/git-svn/.rev_SVN_REVISION_HERE'
     rev = 100
     ref = subprocess.Popen(['git-rev-parse', 'tmp-map'],
         stdout=subprocess.PIPE).communicate()[0].strip()
     f = open(dbfile, 'a')
     f.write(struct.pack('!i', rev))
     f.write(binascii.hexlify(ref))
     f.close()
  7. You can delete the tmp-map branch and the corresponding git-svn info now if you want:

     git branch -r -d tmp-svn
     rm -rf .git/svn/tmp-svn

Hope this helps!