views:

529

answers:

2

I'd like to convert a repository from Subversion to Mercurial, but when I initially set up the repository, I did it in the laziest way possible. Over time, the structure continued to morph and deteriorate (it's 5 years old at this point). Nevertheless, I'd like to preserve as much history as possible, even if I have to get dirty and manually stitch things back together.

Without further ado, the current structure looks like so:

svn://svn.example.com/Example
    + trunk
        + BigProject
        + BinaryDepedencies
    + branches
        + BigProject
            + branch1
            + feature1
            + maintenance1
            + ...
    + tags
        + BigProject
            + tag1
            + tag2
            + ...
    + projects
        + small_project1
        + small_project2
        + small_project3
        + ...

Given that this is just the most recent structure, is there any hope for this repository? If there is no hope, anyone have a good approach for rebuilding the history by hand in Mercurial (or bazaar).

Also, for various reasons, I won't be able use git unless there is a bulletproof strategy to convert this specific repo from Subversion to git to hg/bzr.

+3  A: 

One strategy might be to convert the trunk. You might have to play some games if your trunk has moved, but it shouldn't be too hard.

Another tool in your arsenal might be hg->hg conversion and the rebase extension. You can use those to fiddle around with your tree after you have things in an hg repository and graft on branches after you've converted them. Or graft in new pieces of your trunk history after its moved.

Here is a nice link to documentation on the Mercurial rebase extension.

Basically, here's the strategy you would follow... First, use the convert extension or hgsvn to convert parts of the repository. This may result in multiple lines of trunk, or in branches that are in a separate repository from the mainline.

If you have two sections of trunk in separate repositories and the one in the directory called second directly follows the one in the directory called first, you can do this:

cd second
hg log -r 0
# Note the revision hash
cd ../first
hg tip
# Again, note the revision hash
hg pull -f ../second
hg rebase --source <revision hash from hg log -r 0> --dest <revision hash from hg tip>

That will graft one section of trunk onto another section of trunk.

If you have a branch in a separate repository, the procedure is slightly trickier:

cd branch
hg log -r 0
# Note the revision hash
cd ../trunk
# Find the revision that the branch branches off from and note its hash.
# We will call this revision the 'branch base'.
hg pull -f ../branch
hg rebase --source <revision hash from hg log -r 0> --dest <revision hash of branch base>

That will graft the branch onto the main tree.

Omnifarious
Can you explain how to graft on branches? The hg->hg idea sounds promising.
@throttled - There, I made more of an attempt to explain. :-)
Omnifarious
Awesome, thank you. That gives me a bit to chew on.
+2  A: 

According to the convert extension's docs, something like the following should work.

$ cat > ~/.hgrc <<EOF
[extensions]
hgext.convert=
EOF
$ hg convert --config convert.svn.trunk trunk/BigProject --config convert.svn.branches branches/BigProject --config convert.svn.tags tags/BigProject svn://svn.example.com/Example newhgrepo
jamessan
Very nice suggestion, it seems like I can try using the same strategy to split off the small projects into their own repo.