Combining multiple SVN repositories into one
SvnSvn Problem Overview
After considering the answers to my previous question (One SVN Repository or many?), I've decided to take the 4 or so repositories I have and consolidate them into one. This of course leads to the question, what's the best way to do this?
Is there a way to combine two or more repositories maintaining the version history for both?
Edit: I should also point out that I'm using Assembla.com, which does not provide access to the svnadmin command, AFAIK
Another edit: Does this even matter? If svnadmin works on URLs, then it's no problem then.
Svn Solutions
Solution 1 - Svn
Edit: Oh well, the question edit was made while I was typing. This is an answer to
> Is there a way to combine two or more > repositories maintaining the version > history for both?
Assuming that
The existing repositories have a structure like:
- repository root
- branches
- tags
- trunk
and you want a structure something like:
- repository root
- projectA
- branches
- tags
- trunk
- projectB
- branches
- tags
- trunk
Then for each of your project repositories:
svnadmin dump > project<n>.dmp
Then for each of the dump files:
svn mkdir "<repo url>/project<n>"
svnadmin load --parent-dir "project<n>" <filesystem path to repos>
More complex manipulations are possible, but this is the simplest, most straightforward. Changing the source repository structure during a dump/load is hazardous, but doable through a combination of svnadmin dump
, svndumpfilter
, hand-editing or additional text filters and svnadmin load
Dealing with a third party provider
- Request
svnadmin dump
files for each of your repositories. The provider should be willing/able to provide this - it is your code! - Create an SVN repository locally.
- Perform the actions listed above for the dump files.
- Verify the repository structure is correct with your favorite client.
- Create a dump file for the combined repositories.
- Request that the provider populate a new repository from this dump file.
YMMV: This seems to be a reasonable approach, but I've never worked with a third party provider like this.
Solution 2 - Svn
With Subversion 1.7, you are now able to do dumps remotely. That is, without having access to the local file system and the svnadmin dump
command.
You can use svnrdump
to get a complete dump of a remote repository. See the documentation for syntax details.
Note that the server does not have to be running 1.7, only the client.
http://svnbook.red-bean.com/en/1.7/svn.ref.svnrdump.c.dump.html
Solution 3 - Svn
Yes, using svnadmin dump and svnadmin load.
Let's assume that you have to repositories, one with HEAD revision 100 and the other with HEAD revision 150.
You dump the first repository and load it in the new one: you end up with the full story of the first repository, from revision 0 to revision 150.
Then you dump the second repository and load it in the new one: it gets loaded with its full history, the only things that change are the actual revision numbers. The history of the second repository will be represented in the new repository from revision 151 to revision 250.
The full history of both repositories is preserver, only the revision numbers change for the repository that is imported for second.
The same of course applies for more than two repositories.
EDIT: I posted while you were editing, so I didn't see your note...
Solution 4 - Svn
You can load many dump files in one repository with the following steps.
Repository root:
projectA
branches
tags
trunk
projectB
branches
tags
trunk
First you must create the directory (project A, project B) in your repository root like this:
$ svn mkdir -m "Initial project root" \
file:///var/svn/repository_root/Project_A\
file:///var/svn/repository_root/Project_B\
file:///var/svn/repository_root/Project_C\
Revision 1 committed.
And after that you can load your dump files:
Use the parameter --parent-dir DIRECTORY
$ svnadmin load /var/svn/repository_root --parent-dir Project_A < file-dump-PRJA.dump
…
$ svnadmin load /var/svn/repository_root --parent-dir Project_B < file-dump-PRJB.dump
This way you'll have a repository which contains many dumped repositories.
Solution 5 - Svn
If you don't have access to svnadmin, it would be hard but doable. Let's say you have repositories A and B, and want to merge them into repository C. Here's the steps you would have to use to accomplish this.
-
Check out revision 1 of repository A to your hard disk.
-
Create a directory, called Repository_A on the root of your C repository, and check this out to your local hard disk.
-
Copy the files from your check out of A (minus) the .svn files, to your checkout of C, in the Repository_A folder.
-
Perform a Commit on C.
Update your working copy of repository A to revision 2 , and perform steps 3 and 4, and repeat with each successive revision until you reach the head.
Now do the same with B.
This would basically do the same as @Davide Gualano was suggesting, without requiring svnadmin. You could probably write a simple script to do this for your, of if there aren't a lot of revisions, you could just do it manually.
Solution 6 - Svn
The other answers for this question enabled me to make the script below. Adapt the REPOS map for your case. Also, you may want to move the tags and branches into a "preaggregate" directory in stead of directly into the new branches and trunk.
#!/bin/bash
NEWREPO=$(pwd)/newrepo
NEWREPOCO="${NEWREPO}_co"
DUMPS=repodumps
REV="0:HEAD"
REPOROOT=/data/svn/2.2.1/repositories/
TOOLDIR=/opt/svn/2.2.1/bin/
PATH=${PATH}:${TOOLDIR}
# Old Repository mapping
declare -A REPOS=(
[BlaEntityBeans]='(
[newname]="EntityBeans"
)'
[OldServletRepoServlet]='(
[newname]="SpreadsheetImportServlet"
)'
[ExperimentalMappingXML]='(
[newname]="SpreadsheetMappingXML"
)'
[NewImportProcess]='(
[newname]="SpreadsheetImportProcess"
)'
)
dump() {
rm -fr ${DUMPS}
mkdir ${DUMPS}
for repo in "${!REPOS[@]}"
do
local dumpfile=${DUMPS}/${repo}.dmp
echo "Dumpimg Repo ${repo} to ${dumpfile}"
svnadmin dump -r ${REV} ${REPOROOT}/${repo} > ${dumpfile}
done
}
loadRepos() {
# new big repo
rm -fr ${NEWREPO}
svnadmin create ${NEWREPO}
svn mkdir file:///${NEWREPO}/trunk -m ""
svn mkdir file:///${NEWREPO}/branches -m ""
svn mkdir file:///${NEWREPO}/tags -m ""
# add the old projects as modules
for currentname in "${!REPOS[@]}"
do
declare -A repo=${REPOS[$currentname]}
local newname=${repo[newname]}
echo "Loading repo ${currentname} soon to be ${newname}"
dumpfile=${DUMPS}/${currentname}.dmp
# import the current repo into a trmporary root position
svn mkdir file:///${NEWREPO}/${currentname} -m "Made module ${currentname}"
svnadmin load --parent-dir ${currentname} ${NEWREPO} < ${dumpfile}
# now move stuff arround
# first rename to new repo
svn move file:///${NEWREPO}/${currentname} file:///${NEWREPO}/${newname} -m "Moved ${currentname} to ${newname}"
# now move trunk, branches and tags
for vc in {trunk,branches,tags}
do
echo "Moving the current content of $vc into ${NEWREPO}/${vc}/${newname}"
svn move file:///${NEWREPO}/${newname}/${vc} file:///${NEWREPO}/${vc}/${newname} -m "Done by $0"
done
svn rm file:///${NEWREPO}/${newname} -m "Removed old ${newname}"
done
}
dump
loadRepos