Subversion Administration: Separate an SVN Repository into Individual Projects

Filed under

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:

  1. Dump the current repository
  2. Separate folders in the dump to separate files with svndumpfilter
  3. Create new repositories
  4. Load the filtered dump files into the new repositories
  5. Cleanup the new repository layout, move files from trunk/projectN to trunk/
  6. 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.

Share