Converting a subversion repository created by svn-buildpackage to git (with all history intact), is more difficult than it seems. While git has 2 tools for working with subversion repositories, the structure of the svn-buildpackage repository is problematic. The typical repository created by svn-buildpackage has a structure like this:
package/trunk/
tags/
tags/1.0-1/
branches/
branches/mybranch/
upstream/
upstream/current/
1.0/Both git-svn and git-svnimport will have problems with this setup due to the subdirectories of upstream in the branches directory. If you need to keep the svn repository and want to continue to work with it (using git to push changes back to the svn repository), then you'll have to use git-svn and live with the strange setup.
Alternatively, you can manually use git-svnimport. To avoid the problems described above with the upstream subdirectories, the following AWK script can be used to reassign upstream to a single branch directory:
# print_status = 0 => print normally
# 1 => skip the current block (look for PROPS-END)
# 2 => end of block found, now just skip empty lines
/.+/ {
# Ready to print data again (non-empty line)
if (print_status == 2) {
print_status = 0
}
}
/^PROPS-END$/ {
# End of not printing, skip the empty lines though
if (print_status == 1) {
print_status = 2
}
}
/^Node-path:( |.*\/)tags$/ {
# Make sure the tags directory is not created twice
if (tags_created == 1) {
print_status = 1
}
tags_created = 1
}
/^Node-path:( |.*\/)branches\/upstream\/current/ {
# Remove the current from the upstream directory
sub("/current", "", $2)
if ($2 ~ /branches\/upstream$/) {
# Would create the upstream directory again, instead use it
# to create the tags directory, if necessary, otherwise skip it
if (tags_created == 1) {
print_status = 1
}
tags_created = 1
sub("branches/upstream","tags",$2)
}
if (print_status == 0) print $1, $2
next
}
/^Node-path:( |.*\/)branches\/upstream\// {
# Switch all upstream tags to the tags directory
sub("branches/upstream/", "tags/upstream-", $2)
if (print_status == 0) print $1, $2
next
}
/^Node-copyfrom-path:( |.*\/)branches\/upstream\/current/ {
# Make sure all copies from current now come from upstream
sub("/current", "", $2)
if (print_status == 0) print $1, $2
next
}
/^Node-copyfrom-path:( |.*\/)branches\/upstream\// {
# Make sure all copies from upstream tags come from the tags directory
sub("branches/upstream/", "tags/upstream-", $2)
if (print_status == 0) print $1, $2
next
}
{
if (print_status == 0) print
}To use this script, first dump the entire repository to a file using the "svnadmin dump" command. Then, run this script on the file, which will change branches/upsteam/current to just branches/upstream, and move branches/upstream/<version> to tags/upstream-<version>. Then use "svnadmin create" and "svnadmin load" on the result to load the modified repository structure into a temporary svn repository. Finally, run git-svnimport on the temporary repository. For the structure shown above, this results in branches of origin and master (both point to the trunk), mybranch, and upstream. There should also be tags, in this case upstream-1.0 and 1.0-1.
If your repository contains more than one package you'll need to filter the dump produced by "svnadmin dump" to just include information about this package. Indeed the awk script above only works with one package (actually only one "tags" directory) in the dump. To filter use something like "svndumpfilter include package < full-svn.dump > filtered-svn.dump" -- NicolasDuboc 2008-10-24
