3

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?

4
  • BTW, I can't imagine in real-life nifty_feature or gnarly_feature repo repo Commented Oct 30, 2015 at 19:27
  • Alas, but both of those are real life problems for specific branches in my actual repos. There's another pathological case, too: multiple heads. But git just can't handle that, so I have to make sure those branches wind up merged or split such that they only have a single head each. Commented Oct 30, 2015 at 20:01
  • branches in single repo - OK (maybe), separate forks with strange roots - not OK Commented Oct 30, 2015 at 20:29
  • For multiple heads - bookmark each head of default Commented Oct 30, 2015 at 20:54

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

1 Comment

Once I use convert to rename default, I'll have 100% new changesets. Even changesets also present in the master repo will be converted. The pull will cause me to have two copies of every changeset in the history, one in default and one in the feature branch.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.