How do I import part of repository A into repository B with full revision history intact?
Meet your new friends
svnadmin dump and
This must be done on the host that actually has the repository on it (it can't be done remotely like you can with normal svn commands).
svnadmin dump /var/www/svn/reposA/ > ~/reposA.svn_dump ... * Dumped revision 18.
sudo svnadmin load /var/www/svn/reposB/ --parent-dir some_dir < ~/reposA.svn_dump ... ------- Committed new rev 494 (loaded from original rev 18) >>>
Question: Does the "parent-dir" have to already exist in the target repository?
Yes! So you may have to svn mkdir the directory first. Unless you want to get fun errors like this:<<< Started new transaction, based on original revision 1 svnadmin: File not found: transaction '148-1', path 'parent_dir_that_was_expected_to_already_exist/lib'
A common pattern/use for this technique is when you want to import a smaller repository B into a larger repository A as a subdirectory called B... ([repository refactoring (category)]) You decided, for example, that you'd rather have one big repository that contains all of your projects instead of one repository per project.
> svnadmin dump ~/repositories/my_project_B/ > ~/my_project_B.svn_dump > svn mkdir http://url/to/main_repository/my_project_B -m 'Creating directory into which my_project_B will be imported' > sudo svnadmin load ~/repositories/main_repository/ --parent-dir my_project_B < ~/my_project_B.svn_dump
Meet your new friend
svndumpfilter... It simply applies a directory filter to a dump file, letting you either exclude a certain directory from the dump file or include (only) the directories that you specify.
$ cat ~/svn_dumps/reposA.svn_dump | svndumpfilter include frontend > ~/svn_dumps/reposA-only_including_frontend_dir $ cat ~/svn_dumps/reposA.svn_dump | svndumpfilter exclude backend > ~/svn_dumps/reposA-everything_except_backend_dir
Question: Can it also include/exclude files or does it only work for directories?
svndumpfilter can't do both an exclude and an include in the same operation===
So you can'd do this, for example:
$ cat ~/svndumps/89glass | svndumpfilter --include: frontend --exclude: frontend/include > ~/svndumps/glass-89glass-web
But you can always do two consecutive
svndumpfilter operations to achieve just about any combination you could want...
$ cat ~/svndumps/89glass | svndumpfilter include frontend/ backend/ > ~/svndumps/89glass-frontend $ cat ~/svndumps/89glass-frontend | svndumpfilter exclude frontend/include/ > ~/svndumps/89glass-frontend-without_include $ ...
svndumpfilter: Invalid copy source path '/dirA_old_name'
I think when this has happened to me before it is because I was using
svndumpfilter include to include dirA, but dirA was a copy (or move) of
dirA_old_name so it was unable to include
dirA without including its ancestor from previously, which happened to have been called
dirA_old_nameback in the day.
dirA_old_name was moved/copied to
svndumpfilter include dirA_old_name dirA
instead of just:
svndumpfilter include dirA
I don't think you need to worry about the unwanted old directory
svndumpfilter include ending up existing in your dump file (and thus your new repository). It simply needs to be able reference that old revision so that it can calculate what the later revisions look like -- but if
dirA_old_name was deleted/moved, then it shouldn't end up existing in the current version. In other words, svndumpfilter needs to be able to look at that old directory to be able to figure stuff out, but that doesn't mean it will actually keep the directory in its final results (so you might argue that having to list it in the include option is misleading...).
Lesson learned: Even if a directory doesn't exist in the current revision of a repository, you may still need to include it in your
svndumpfilter include command to avoid getting errors.
> cat dumps/everything | svndumpfilter include gemables/rake_command_completion/ > dumps/rake_command_completion
But now when I tried this...
> sudo svnadmin load /var/www/svn/code-copy/ < dumps/rake_command_completion
~file not found
So I tried it again, differently...
> sudo rm -rf /var/www/svn/code-copy > sudo svnadmin create /var/www/svn/code-copy > sudo svn mkdir file:///var/www/svn/code-copy/gemables//rake_command_completion -m 'Creating parent directories that svnadmin load might expect to be there'
Interestingly, I got the same error message here that I'd gotten when I tried to do the svnadmin load!
~file not found
... which is further evidence that all I need to do is create in the new repository all parent directories of the path (
gemables/) that I originally dumped (
This is what finally worked for me...
> sudo svn mkdir file:///var/www/svn/code-copy/gemables/ -m 'Creating parent directories that svnadmin load might expect to be there' > sudo svnadmin load /var/www/svn/code-copy/ < dumps/rake_command_completion > out &
> svn co file:///var/www/svn/code-copy/ A code-copy/gemables A code-copy/gemables/rake_command_completion ...