Search code examples
mercurialmerge

Merging two different repositories


I've 3 repos, A, B and C, all related to the same project. A is the oldest version of the project, B is an experiment that didn't really go anywhere and C is the latest working version. All these repos have different files - they're different implementations of the same product.

I'd like to merge these 3 repos into one keeping their history - this is vital. I guess I want to stack B on top of A and C on top of B but when I checkout the project I only want to get the changes related to repo C.

My idea is to tag or create a named branch on A, hg rm *, commit and then pile B on top. Repeat the same with B so I can pile C and then continue on the project as usual.

What do you think? Also, some inspiration for what I want to do: 1, 2.


Solution

  • You can just pull the changesets into one big repository. Start with the A repo:

    $ hg init combined
    $ cd combined
    $ hg pull ../A
    $ hg update
    

    Then forcibly pull in B and dummy-merge the two heads so that you keep the files from B:

    $ hg pull ../B --force
    $ hg merge --tool internal:other
    $ hg revert --all --rev tip
    $ hg commit -m "Merge A and B, kept B"
    

    Then repeat for C:

    $ hg pull ../C --force
    $ hg merge --tool internal:other
    $ hg revert --all --rev tip
    $ hg commit -m "Merge B and C, kept C"
    

    That gives you three lines of history and a merge point where you first throw away A, then B, and finally end up with C.

    Alternatively you can use the convert extension with a splice map to splice the three histories together. Start by forcibly pulling all the changesets into a single repository. Then do a Mercurial to Mercurial conversion where you add the tip of A as the first parent of the root of B. Similarly for B and C. That gives you one long history where there will be a very abrupt change when you go from A to B and from B to C.

    I would go with the first option: it's the most explicit and shows best what happens without faking (converting) the history.