I have a giant VisualSVN repository with the following structure
/common
└── ^/trunk
├── proj1
│ └── CMakeLists.txt
├── proj2
│ └── CMakeLists.txt
└── projN
└── CMakeLists.txt
5 years, and 19,000 commits later ... I want branching that actually works. So I'd like to split that repository into several smaller ones
/proj1
├── ^/branches
└── ^/trunk
└── CMakeLists.txt
/proj2
├── ^/branches
└── ^/trunk
└── CMakeLists.txt
/projN
├── ^/branches
└── ^/trunk
└── CMakeLists.txt
How do I do this?
I'm happy to use client-commands svn mv
to get the structure right, but the biggest thing is filtereing out all of content I don't want.
I've started by using svnadmin
to create a 4GB dump file of the full repository
D:\Repositories> svnadmin dump D:\Repositories\common > common.dump
* Dumped revision 0.
* Dumped revision 1.
...
* Dumped revision 18968.
* Dumped revision 18969.
Then I'm using svndumpfilter
to reduce this to only the revisions related to the project of interest:
D:\Repositories> svndumpfilter \
--drop-empty-revs \
--renumber-revs \
include trunk/proj1 \
< common.dump > proj1.dump
Including (and dropping empty revisions for) prefixes:
'/trunk/proj1'
Revision 0 committed as 0.
Revision 1 skipped.
Revision 2 skipped.
...
Revision 561 committed as 1.
...
Revision 669 committed as 2.
...
Revision 13514 committed as 36.
svndumpfilter: E200003: Invalid copy source path: '/trunk/proj2/file' for `/trunk/proj1/file`
This failed because there was an svn mv ^/trunk/proj2/file ^/trunk/proj1/file
performed at some point. I can deal with that by simply adding another include
:
D:\Repositories> svndumpfilter \
--drop-empty-revs \
--renumber-revs \
include \
trunk/proj1 \
trunk/proj2/file \
< common.dump > proj1.dump
...
Revision 13515 comitted as 38.
svndumpfilter: E200003: Missing merge source path '/branches/proj1-tests'; try with --skip-missing-merge-sources
Getting closer, and I don't really need merge history, so I'll do what's recommended and add --skip-missing-merge-sources
D:\Repositories> svndumpfilter \
--drop-empty-revs \
--renumber-revs \
--skip-missing-merge-sources \
include \
trunk/proj1 \
trunk/proj2/file \
< common.dump > proj1.dump
Success! In reality, I have about 100 things that I've included. Now I'd like to use this to create that new repository:
D:\Repositories> svnadmin create proj1
D:\Repositories> svnadmin load --ignore-uuid proj1 < proj1.dump
<<< Started new transaction, based on original revision 1
* editing path : trunk/proj2/file
...svnadmin: E160013: File not found: transaction '0-0', path '/trunk/proj2/file'
And now I'm stuck. How do I deal with that?
The problem is the revision which created trunk/proj2
isn't included. You could add include trunk/proj2
, but you could end up adding the whole tree and that just defeats the purpose of filtering.
Then you could spend time refining your filters, but there's a script deployed with svnadmin that already does that: svnrdump
.
D:\Repositories> svnrdump dump file:///Repositories/common/trunk/proj1 > proj1.dump
D:\Repositories> svnadmin create proj1
D:\Repositories> svnadmin load proj1 < proj1.dump
D:\Repositories> del proj1.dump
Or using piping:
D:\Repositories> svnadmin create proj1
D:\Repositories> svnrdump dump file:///Repositories/common/trunk/proj1 | svnadmin load proj1
Then checkout a working copy and svn mv
as appropriate.
D:\Temp> svn checkout file:///Repositories/proj1 proj1.wc
D:\Temp> cd proj1.wc
D:\Temp> svn move trunk/proj1/* trunk/
D:\Temp> svn remove trunk/proj1
D:\Temp> svn commit
There might be a way to include --drop-empty-revs --renumber-revs
, but I haven't found it yet. I tried the following but it didn't filter out very much:
svnrdump dump file:///Repositories/common/trunk/proj1 > proj1.dump
svndumpfilter --drop-empty-revs --renumber-revs include / < proj1.dump > proj1-filtered.dump
svnadmin load proj1 < proj1-filtered.dump