Search code examples
gitmercurialbranchdvcsmercurial-convert

How can I convert a Git repository with branches to a workable Mercurial repository?


I want to convert a Git repository with several branches to a Mercurial repository. Using hg convert only one default branch is created which then has a head for each Git branch.

I have already read How are git branches imported into mercurial with hg convert? and am aware that it is impossible to know which commit belongs to which branch in Git. However, a repository with as many heads as branches is not a workable solution for me.

Since all branches are different, I obviously can not merge them all to one single head.

How can I convert or modify the converted repository in such a way that I have each head on a different branch? Note that I do not necessarily need to have all existing commits assigned to the right branch but that I want commits from this moment on to be assigned to the right branch and only have one head per branch.


Solution

  • You must to know some things about Git:

    • Git "branches" are not branches for any other good VCS, for Mercurial, f.e they are bookmarks by nature ("branch" mark only head-changeset and any older changeset doesn't contain this metadata)
    • When Git-boy speak about branches - he lies, because branches are branches only in his Git-world
    • Noboby (today) will convert Git-"branches" into branches on converting repositories
    • In most cases (except very exotic Git-repos) hg-git instead Convert Extension will produce more correct (bidirectional) conversion

    Specially for you I repeated operations from (excellent in common) VonC answer in linked by you question and will show you some pictures (Git's from SmartGit, Mercurial's from TortoiseHG)

    After all commits,

    GitRepo>git log --oneline
    79ea101 third evolution in branch 2
    720ac25 second evolution in branch 2
    48951c3 first evolution in branch 2
    6cf26b0 first content, to be evolved in three different branches
    

    before importing to Mercurial, with all "branches"

    Git-repo

    From Mercurial's POV, results of import is very different: repository have one real branch (named branch default) and 3 anonymous branches in it, marked with Mercurial bookmarks br1-br2-br3.

    HG-repo

    You must to create named branches and rewrite history by hand, if you want to use Mercurial named branches in this repository:

    • commit new empty changesets as descendants of 0, they will be starting point of branches
    • rebase anonymous branches to these new parents (change actual branches)

    Rebased HG-repo

    As optional and the last step you can remove created at step 1 empty changesets (histedit do it well) and all useless bookmarks

    Clean HG-repo