简体   繁体   中英

How do I convert a set of mercurial repositories into a git repository?

What I have

I currently have a set of mercurial repositories that contain source code. They use the “forked repository” scheme for branches. So, a feature “branch” might look like this:

master repo           A→B→C
                    ———————↘—————
cool_feature repo           D→E→F

Once cool_feature is ready for prime time, we hg pull it into master so that it will look like this:

master A→B→C→D→E→F

At that point, cool_feature will have the same stuff as master and it can be discarded.

Although D→E→F are in a separate repository at some points in time, they are always on the “default” branch in mercurial. We do not use named branches to manage this data.

This works well in mercurial, but we're planning to move to git and git does things a little differently. You can still fork repos in git, of course, but git branches are ephemeral and therefore usable for short-lived branches.

What I want

I'd like to convert this to a single git repository that uses branches to manage work still in inventory. In terms of process, we'll be using basically “git flow”. Pull requests will be between branches and once the work is complete, branches will be deleted.

master branch           A→B→C
                     ————————↘—————
cool_feature branch           D→E→F

What I've tried

I can't simply use hg's convert , because it doesn't understand multiple repositories. In fact, every tool in the entire hg-git ecosystem seems to want to convert git branches to hg branches and vice versa. (Despite evidence that suggests that the various communities use them very differently in practice.)

One idea is to pull them into a single repository, convert it, then let git sort it out. After all, git only really needs to label the heads. The problem with this idea is most tools refuse to convert a multi-headed repository and if they do, git quietly discards the unlabeled heads as is its wont. If it's possible to label them after-the-fact, I haven't figured it out.

Another idea is to, within mercurial, move those changesets to a named branch and let the repository converter do the work. This is tricky, because branches don't always start at a single spot:

master repo            A→B→C→F→G→H
                     ———————↘—————↘————————
nifty_feature repo           D→E   I→J
                                \    ↓
                                 +——→K→L→M (K is a merge of E and J)

This situation usually arises when two developers start work on a project together, but don't wind up with exactly the same changeset as their starting point. But there's no single point to select as the “upline” from which to create a branch.

Another gnarly situation is when the first revision is a merge:

master repo          A→B———→C
                        \    \
                         +→D  \
                    ————————\——↘—————————
gnarly_feature repo          +—→E→F

Here, the “root” of the branch is E , a merge between C and D . It's not immediately clear to me how you'd rebase that to a new branch, given that it is a merge revision.

For other reasons, I'm already running the conversion via reposurgeon, so I have access to some fairly fancy tools for modifying it in-flight. But every conversion takes ~20 hours, so trying a bunch of things that don't pan out has proven very expensive.

But it seems that since people do convert from hg to git and these are each commonly used branching schemes, somebody out there has surely solved this problem. Any ideas for what tools to use or what strategies to try are welcome. How does one accomplish this?

they are always on the “default” branch in mercurial. We do not use named branches to manage this data

It's big error: you can use named branch+separate clone at the same time

I'd like to convert this to a single git repository that uses branches to manage work still in inventory

It can be big error 2 (in direction /from Hg to Git/ and methodology /single repo/)

every tool in the entire hg-git ecosystem seems to want to convert git branches to hg branches and vice versa.

Just wrong. I have Git-repo in hands, cloned with hg-git with a set of Git-branches . On Mercurial's side I have (as expected) single branch

>hg branches
default                     5266:1ffe854c93c1

and Git-branches, presented as hg-bookmarks (which they are really)

>hg book
   1.6                       2344:fc32e948fcba
   1.7                       5140:1c58e9bfa3d5
   2.0                       5219:683d072d02b6
   feature_dbpluginapi       4986:a855a635e17f
   feature_indexCleanup      5207:7ec7ee38ef2f
   feature_preview           4806:d40ade50b113
   feature_updateAll         4807:97ea12fea917
   master                    4620:de0053588acf

I can't simply use hg's convert, because it doesn't understand multiple repositories

But you have to use it for per-repository conversion:

  • Convert each feature-repo into intermediate Mercurial-repo, using --branchmap option (rename default branch into another... feature-name?)
  • Pull converted repo into master-repo; you have to get full history, identical to old, with one exception: all feature-development will appear in unique named branches
  • Push aggregated repo to Git with hg-git or Git-Hg bridge

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM