I had a client who contracted a Chinese firm to do some development for them. When they came to me, they cited the language barrier as one of the reasons they were having a hard time getting their ideas into production. SUPPLIES! Translation: Surprise (but not a surprise to me). So the first order of business was moving their code repository stateside.

The normal way: svnadmin dump

Conventional logic lead me to starting with: svnadmin dump

What happened was svnadmin dump would get partly through it’s export and the connection would inevitably drop. This left me with a partial dump that was really of no value.

Given the size of the repository (huge) and the quality of the link to the repository (terrible), it was time to find another solution. I still wanted revision history to be retained, so instead of using svnadmin dump, I decided to try svnsync

The foolproof way: svnsync

svnsync requires a second repository to sync to. No problem, just set up a local repository:

$ cd /tmp
$ svnadmin create local.repos
$ echo '#!/bin/sh' > local.repos/hooks/pre-revprop-change
$ chmod +x local.repos/hooks/pre-revprop-change
$ svnsync init file:///tmp/local.repos http://remote.repository.bfe/repository_root
$ svnsync sync file:///tmp/local.repos

I don’t know why svnadmin create doesn’t give you a base (empty) pre-revprop-change, but it doesn’t, so lines 3 & 4 above are needed.

synsync sync is where the magic happens. It syncs the entire repository one commit at a time. So if (and when) it fails, you can simply re-run that last svnsync sync command again, and it will resume where it left off.

Once that’s done we have to take some extra steps to be able to switch/relocate any checkouts to the new repository URL. Otherwise subversion is going to complain about the repository UUIDs not matching:

svn: The repository at '...' has uuid '5242f4d0-6d7c-4812-b150-1df843629073', but the WC has 'add5d305-2225-4d42-af3e-22d1851a68c1'

So we need to reset some of the properties on the local copy of the repository. The easiest way to do this is to checkout the repository locally and run a few commands for it:

$ svn checkout file:///tmp/local.repos local.checkout
$ svn proplist --revprop -r0 local.checkout
Unversioned properties on revision 0:
  svn:sync-from-uuid
  svn:sync-last-merged-rev
  svn:date
  svn:sync-from-url
$ svn propdel svn:sync-from-uuid --revprop -r0 local.checkout
$ svn propdel svn:sync-last-merged-rev --revprop -r0 local.checkout
$ svn propdel svn:sync-from-url --revprop -r0 local.checkout

The revprop changes are not versioned changes, so they take effect immediately – there’s no need to commit them. Now we need to set the UUID of the local repository to that of the old remote repository.

$ svn info http://remote.repository.bfe/repository_root
...
Repository UUID: add5d305-2225-4d42-af3e-22d1851a68c1
...
$ svnadmin setuuid local.repos add5d305-2225-4d42-af3e-22d1851a68c1

The repository is now ready for svnadmin dump (again)

With the repository fully copied, and the UUID sorted, you can move it to it’s final destination. If it’s ultimately going to a hosted repository (like repositoryhosting.com) you can dump the local repository to use for importing at the new host:

svnadmin dump local.repos > local_svn_dump

Once your repository is at it’s new location, you can switch any checkouts so they’re pointing to the new location:

svn switch --relocate http://remote.repository.bfe/repository_root http://new.repository.us/svn_root

It should be noted that as of svn version 1.7 svn switch --relocate has been deprecated in favor of svn relocate

Leave a Reply