Subversion Administration: Separate an SVN Repository into Individual Projects
I've been using Subversion since the Gallery Project switched to it from CVS a few years back. I decided to install Subversion to manage my freelance projects last year and am getting up to speed on repository administration. I flip-flopped for a while on whether to keep projects in a single or separate repositories. I initially decided to keep everything in one repository, but later decided to separate them out. Fortunately, the svnadmin and svndumpfilter utilities make it relatively simple to separate repositories into individual projects.
My goal is to create two new projects from folders stored in the trunk of a single repository. My repository's history isn't complex—it doesn't contain tags or branches yet. You'll need to put a bit more thought into how to deal with existing tags and branches.
My current svn root layout is:
/svnroot
/branches
/tags
/trunk
/project1
/project2
The desired layout is:
/svnroot
/project1
/branches
/tags
/trunk
/project2
/branches
/tags
/trunk
The basic steps to separate these repositories are:
- Dump the current repository
- Separate folders in the dump to separate files with svndumpfilter
- Create new repositories
- Load the filtered dump files into the new repositories
- Cleanup the new repository layout, move files from trunk/projectN to trunk/
- Delete the original branches, tags, and trunk repositories from svnroot
I'll use tmp as working directory to dump and filter files.
Dump the current repository
svnadmin dump /svnroot/originalproject > /tmp/original.dump
Separate folders to separate files with svndumpfilter
cat /tmp/original.dump | svndumpfilter --drop-empty-revs --renumber-revs include trunk/project1 > /tmp/project1.dump
cat /tmp/original.dump | svndumpfilter --drop-empty-revs --renumber-revs include trunk/project2 > /tmp/project2.dump
The key here is the include option which targets the project folder(s). There's also an exclude option that might come in handy if you're trying to remove one folder from a group of many. The --drop-empty-revs and --renumber-revs options remove commit log messages for other folders and renumber the remaining revision numbers.
Create new repositories
svnadmin create /svnroot/project1
svnadmin create /svnroot/project2
Load the filtered dump files into the new repositories
svnadmin load /svnroot/project1 < /tmp/project1.dump
svnadmin load /svnroot/project2 < /tmp/project2.dump
Cleanup new repository layout, move files from trunk/projectN to trunk/
Each repository layout now looks something like:
/svnroot
/project1
/branches
/tags
/trunk
/project1
file1
...
fileX
But they should look like:
/svnroot
/project1
/branches
/tags
/trunk
file1
...
fileX
Subversion doesn't allow wildcard gobling, so it's impossible to do something like:
svn move trunk/project1/* trunk/
It was possible to edit path information in the project dump files before loading them, but it seemed easier to check out a working copy of each, move things around, and then commit the changes.
svn checkout file:///svnroot/project1 /tmp/project1
cd /tmp/project1/trunk
Now, a little shell work to move things around. Thanks Tigris! PLEASE NOTE: Use this at your own risk. Back up your repository before trying the following or be ready to use svn revert.
for i in /tmp/project1/trunk/project1/*; do svn mv $i /tmp/project1/trunk; done
svn commit -m "Moved all project files to trunk"
svn remove /tmp/project1/trunk/project1
svn commit -m "Removed obsolete project1 folder after moving its contents to trunk"
Lather, rinse, repeat.
At some point I'll probably back track and write a post on installing and configuring Subversion with MacPorts but that's it, at least for now.