Git interoperability with a Mercurial Repository
Asked Answered
I

11

206

I use GIT on a Mac. Enough said. I have the tools, I have the experience. And I want to continue to use it. No wars here...

The problem is always with interoperability. Most people use SVN, which is great for me. Git SVN works out of the box, and is a no frills solution. People can continue happily use SVN and I don't lose my workflow and neither my tools.

Now... Some guys come along with Mercurial. Fine for them: they have their reasons. But I can't find any GIT HG out-of-the-box. I don't want to switch to HG, but I still need to interoperate with their repository.

Any of you guys know a simple solution for this?

Instil answered 19/5, 2009 at 15:26 Comment(2)
hg-git does work in both directions.Armillary
The answer by @dubiousjim is more useful, comprehensive and more up-to-date than the current top two, which are pointing to unmaintained repos or give outdated advice. But yet more updates on this question would be very helpful.Synchronism
S
64

Update from June 2012. Currently there seem to be the following methods for Git/Hg interoperability when the developer wants to work from the git side:

  1. Install Mercurial and the hg-git extension. You can do the latter using your package manager, or with easy_install hg-git. Then make sure the following is in your ~/.hgrc:

    [extensions]
    hggit = 
    

You may see some references that talk about specifying the bookmarks extension here too, but that has been built into Mercurial since v 1.8. Here are some tips about installing hg-git on Windows.

Once you have hg-git, you can use commands roughly like Abderrahim Kitouni posted above. This method has been refined and tweaked since 2009 though, and there is a friendly wrapper: git-hg-again. This uses the toplevel directory as a working directory for both Mercurial and Git at the same time. It creates a Mercurial bookmark that it keeps in synch with the tip of the default (unnamed) branch in the Mercurial repository, and it updates a local Git branch from that bookmark.

  1. git-remote-hg is a different wrapper, also based on the Mercurial hg-git extension. This additionally makes use of the git-remote-helpers protocols (hence its name). It uses the toplevel directory only for a Git working directory; it keeps its Mercurial repository bare. It also maintains a second bare Git repository to make synching between Git and Mercurial safer and more idiomatically gitlike.

  2. The git-hg script (formerly maintained here) uses a different method, based on hg-fast-export from the fast-export project. Like method 2, this also keeps a bare Mercurial repository and an additional bare Git repository.

For pulling, this tool ignores Mercurial bookmarks and instead imports every named Mercurial branch into a Git branch, and the default (unnamed) Mercurial branch into master.

Some commentary discusses this tool as being hg->git only, but it claims to have merged in git->hg push support on 7 Dec 2011. As I explain in a review of these tools, though, the way this tool tries to implement push support doesn't seem to be workable.

  1. There's also another project called git-remote-hg. Unlike the version listed above, this one doesn't rely on hg-git, but instead directly accesses the Mercurial Python API. At the moment, using it also requires a patched version of git. I haven't tried this yet.

  2. Finally, Tailor is a project that incrementally converts between a variety of different VCSs. It sounds like development of this won't be aggressively continued.

The first three of these approaches looked lightweight enough to persuade me to investigate. I needed to tweak them in some ways to get them to run on my setup, and I saw some ways to tweak them further to improve them, and then I tweaked them still further to make them behave more like each other so that I could evaluate them more effectively. Then I thought others might like to have these tweaks too, to do the same evaluation. So I've made a source package that will enable you to install my versions of any of the first three tools. It should also take care of installing the needed hg-fast-export pieces. (You need to install hg-git on your own.)

I encourage you to try them out and decide for yourself what works best. I'll be glad to hear about cases where these tools break. I'll try to keep them in synch with upstream changes, and to make sure the upstream authors are aware of the tweaks I think are useful.

As I mentioned above, in evaluating these tools, I came to the conclusion that git-hg is only usable for pulling from Mercurial, not for pushing.

Relatedly, here are some useful comparisons/translation manuals between Git and Mercurial, in some cases targetted at users who already know Git:

Stanger answered 24/6, 2012 at 15:31 Comment(2)
I'm using method #2 myself, or rather my tweaked version of it. Overall that seems to me the most reliable and flexible approach (of the ones I tried). See the links to my review/source package for details.Stanger
Yup. Kiln Harmony is awesome. Free for solo devs too.Dehiscence
A
117

There's a new git-remote-hg tool that provides native support:

Bridge support in Git for Mercurial and Bazaar.

Just copy git-remote-hg to your $PATH, make it executable, and that's it, no dependencies (other than Mercurial):

git clone hg::https://www.mercurial-scm.org/repo/hg/

You should be able to push and pull from it as if it was a native Git repository.

When you push new Git branches, Mercurial bookmarks will be created for them.

See the git-remote-hg wiki for more information.

Aquilar answered 13/11, 2012 at 2:52 Comment(3)
Make sure you name it exactly git-remote-hg (i.e. no .py suffix).Nobel
Works when the hg repository is a submodule as well.Bettor
@AntoinePelisse: You're right, just install it via pip install mercurial.Berkow
K
107

You should be able to use hg-git.

hg clone <hg repository>

edit ~/.hgrc and add :

[extensions]
hgext.bookmarks =
hggit =

create a bookmark so you will have a master in git :

cd <repository>
hg bookmark -r default master

edit .hg/hgrc in the repository and add :

[git]
intree = true

now you can create the git repository :

hg gexport

and you can use the resulting directory as a git clone. pulling from mercurial would be :

hg pull
hg gexport

and pushing to mercurial :

hg gimport
hg push

(Yes, you need to use hg with this workflow but your hacking will be all in git)

P.S. If you have a problem with this workflow, please file a bug.

Knightly answered 6/7, 2009 at 21:6 Comment(12)
don't forget to run easy_install hg-git firstDromous
Not exactly what I wanted, but still doable. Thanks.Instil
Just an fyi, after running through this process once on a local hg repo (and doing something wrong) I wasn't able to clone the resulting repo using git. I had to "hg clone" the source hg repo, follow the steps on the new hg repo, and then git clone the new hg repo.Fatherland
I get this when trying to issue a git status command $ git status fatal: This operation must be run in a work tree This is after I've issued an hg gexport in a freshly cloned hg repository. What is a possible work out to get around bare repositories? Update. Apparently, Rock Burt's suggestion works. Thank youTheocritus
See blog.vucica.net/2011/05/… for more information.Theocritus
I just want to add that, while this would be great if it worked, it doesn't with the above instructions. As two other people have mentioned, you're left with a barebones repo that somehow thinks its on the master branch but git status says otherwise. Also, my commit log looks hideous, 1 git commit ends up being 3 hg commits, and then doing hg status says the file that I just commit hasn't yet been modified. These are a little more than bugs, it just doesn't work.Underpin
I just noticed the date of the answer ('09) compared to those who are having problems with it ('11), that probably means things have changed a bit in the last couple years.Underpin
The problem I'm having is after I run "hg gexport" and then issue a "git status" I get the following: "fatal: This operation must be run in a work tree" Anyone know what could be wrong?Hetero
@Hetero I am get the same exact issue and also trying to figure out how to get it to workManes
What I ended up dong @Manes is popping open my .git/config file and removing bare=true and that seemed to solve thingsHetero
@Hetero I have the same problem. Apparently the git repo is created as .hg/git. The solution is to 'ln -s .hg/git .git'.Tumblebug
Note that if you apt-get install mergurial-git on a Debian/Ubuntu based system, hggit = won't work and you need git = or hgext.git = instead. See Launchpad bugs 666292 and 108876.Moron
S
64

Update from June 2012. Currently there seem to be the following methods for Git/Hg interoperability when the developer wants to work from the git side:

  1. Install Mercurial and the hg-git extension. You can do the latter using your package manager, or with easy_install hg-git. Then make sure the following is in your ~/.hgrc:

    [extensions]
    hggit = 
    

You may see some references that talk about specifying the bookmarks extension here too, but that has been built into Mercurial since v 1.8. Here are some tips about installing hg-git on Windows.

Once you have hg-git, you can use commands roughly like Abderrahim Kitouni posted above. This method has been refined and tweaked since 2009 though, and there is a friendly wrapper: git-hg-again. This uses the toplevel directory as a working directory for both Mercurial and Git at the same time. It creates a Mercurial bookmark that it keeps in synch with the tip of the default (unnamed) branch in the Mercurial repository, and it updates a local Git branch from that bookmark.

  1. git-remote-hg is a different wrapper, also based on the Mercurial hg-git extension. This additionally makes use of the git-remote-helpers protocols (hence its name). It uses the toplevel directory only for a Git working directory; it keeps its Mercurial repository bare. It also maintains a second bare Git repository to make synching between Git and Mercurial safer and more idiomatically gitlike.

  2. The git-hg script (formerly maintained here) uses a different method, based on hg-fast-export from the fast-export project. Like method 2, this also keeps a bare Mercurial repository and an additional bare Git repository.

For pulling, this tool ignores Mercurial bookmarks and instead imports every named Mercurial branch into a Git branch, and the default (unnamed) Mercurial branch into master.

Some commentary discusses this tool as being hg->git only, but it claims to have merged in git->hg push support on 7 Dec 2011. As I explain in a review of these tools, though, the way this tool tries to implement push support doesn't seem to be workable.

  1. There's also another project called git-remote-hg. Unlike the version listed above, this one doesn't rely on hg-git, but instead directly accesses the Mercurial Python API. At the moment, using it also requires a patched version of git. I haven't tried this yet.

  2. Finally, Tailor is a project that incrementally converts between a variety of different VCSs. It sounds like development of this won't be aggressively continued.

The first three of these approaches looked lightweight enough to persuade me to investigate. I needed to tweak them in some ways to get them to run on my setup, and I saw some ways to tweak them further to improve them, and then I tweaked them still further to make them behave more like each other so that I could evaluate them more effectively. Then I thought others might like to have these tweaks too, to do the same evaluation. So I've made a source package that will enable you to install my versions of any of the first three tools. It should also take care of installing the needed hg-fast-export pieces. (You need to install hg-git on your own.)

I encourage you to try them out and decide for yourself what works best. I'll be glad to hear about cases where these tools break. I'll try to keep them in synch with upstream changes, and to make sure the upstream authors are aware of the tweaks I think are useful.

As I mentioned above, in evaluating these tools, I came to the conclusion that git-hg is only usable for pulling from Mercurial, not for pushing.

Relatedly, here are some useful comparisons/translation manuals between Git and Mercurial, in some cases targetted at users who already know Git:

Stanger answered 24/6, 2012 at 15:31 Comment(2)
I'm using method #2 myself, or rather my tweaked version of it. Overall that seems to me the most reliable and flexible approach (of the ones I tried). See the links to my review/source package for details.Stanger
Yup. Kiln Harmony is awesome. Free for solo devs too.Dehiscence
S
15

You can try hg2git, which is python script and is part of fast-export, which you can find at http://repo.or.cz/w/fast-export.git .

You'll need to have mercurial installed though.

Scamander answered 19/5, 2009 at 15:39 Comment(3)
This converted an hg repo into a git repo, thank you very much!Gearhart
This script failed for me, but the original hg-fast-export worked fineUninterested
I think that currently the hg-fast-export script dispatches to hg2git. I haven't traced it all out though. Note that these tools only permit going from Hg->Git, not the reverse.Stanger
D
9

Since hg-git is a two-way bridge, it will also allow you to push changesets from Git to Mercurial.

Drat answered 20/5, 2009 at 21:34 Comment(0)
F
6

Hg-Git Mercurial Plugin. Haven't tried it myself, but might be worth checking out.

Florri answered 19/5, 2009 at 15:32 Comment(2)
This is a plugin which allows mercurial users to push and pull from git repos, not the other way around, which is what the OP wants.Scamander
@sykora, it can be used to drive interoperability from the reverse direction too. See some of the tools I list in my answer.Stanger
S
6

I have had great success with git-hg from https://github.com/cosmin/git-hg (requires working install of hg, too). It supports fetch, pull and push and is more stable for me than hg-git (similar features from hg to git).

See https://github.com/cosmin/git-hg#usage for usage examples. The user interface is very similar to git-svn.

The git-hg requires extra disk space for each cloned hg repo. The implementation uses full mercurial clone, an extra git bare clone and the actual git repo. The required disk space is roughly 3 times the normal git only usage. The extra copies are stored below the .git directory of your working directory (or location pointed by GIT_DIR as usual).

Notice: The basic problem that git-hg tries to solve is that there is no 1:1 mapping between git and hg features. The biggest problem is the impedance mismatch between git branches and hg unnamed branches and hg named branches and hg bookmarks (all of those look a lot like branches to git users). A related problem is that hg tries to save original named branch name in the version history as opposed to git where the branch name is only added to template commit message by default.

Any tool that claims to create interoperable bridge between git and hg should explain how it's going to deal with this impedance match. You can then decide if the selected solution fits your needs.

The solution that git-hg uses is to discard all hg bookmarks and convert named branches to git branches. In addition it sets the git master branch to default unnamed hg branch.

Seduction answered 27/6, 2012 at 9:59 Comment(4)
It looks like git-hg is only viable for pulling from Hg, not for pushing (see the explanation I link to in my answer). Have you found some way to successfully use it in both directions? As to extra space, all of the techniques I'm familiar with involve working dir + one copy of git db/metadata + one copy of hg db/metadata. Adding a second copy of the git db/metadata does involve more disk usage, yes, but comparatively speaking it's not as bad as it may seem.Stanger
@Stanger My needs were fullfilled with a working pull/fetch and I never actually tested the push. I was trusting the documentation but after checking your explanations I now believe that git-hg is not suitable for pushing. I modified my answer to make it more clear that push is not stable enough.Seduction
Too bad, I thought there might be some way to use push successfully that I wasn't seeing.Stanger
+1 for highlighting the impedance mismatch and what to look forPetrolatum
A
3

Have tried hggit. Works for me, since I have to cope the work of git'ers and hg'ers. Especially for reviews this is great.

A minor issue/warning on that topic:

I have tried to clone a stable linux kernel repository with hg. These repositories are maintained in git and typically have a large number of files in it.

It was very slow. Took me 2 days to fully clone and update a working copy.

Absorbefacient answered 4/8, 2011 at 6:45 Comment(7)
It appears to be getting better --- my checkout has been running for about six hours, and it claims there's only another nine to go...Maidservant
I take that back. It's now been running for about 25 hours, and it still claims there's only another nine to go. Two days, you said?Maidservant
I experienced that - My first try didn't work at all - I presume it was some bug, but never analyzed that any further, on my second try - with an updated hg-git it took almost 50 hours to complete on my Mac Book Pro (2.66GHz, 8 Gig RAM)Absorbefacient
39 hours now, so only 11 to go! Quad core AMD Phenom. It is making progress, which is why I'm letting it run (the hg progress bar extension is a must-have). It's alternating between pegging one CPU and using no CPU at all and doing lots of disk access.Maidservant
Has anyone tested if the the poor performance caused by hggit or is hg too slow to be usable with kernel-size projects in general?Seduction
You could probably install and get the hang of Git in those 2 days you were waiting. ;)Dehiscence
For sure, but it was the exploration of the technical possibilities which had me wait so long.. - practically I work with developers who prefer the one over the other so the interoperability of the two systems would ease things :)Absorbefacient
E
2

I have tried cosmin's git-hg and abourget's git-hg-again both on mutt's hg repo, it seems that the later respects the order of a merge well, the former is a bit random. You can see from the screenshots below.

A merge history graph of mutt imported by cosmin's git-hg:

enter image description here

A merge history graph of mutt imported by abourget's git-hg-again:

enter image description here

The actuall history graph plotted by hgk on mutt's hg repository:

enter image description here

As you can see from the above, the second graph by abourget's git-hg-again is very close to the original hgk graph and is actually reflecting the real workflow of the mutt.

One drawback of git-hg-again I found is that it does not add a 'hg' remote, rather imports all its refs as local tags, git-hg has a wonderful 'hg' remote represents the upstream hg repo.

Entreat answered 1/1, 2014 at 17:51 Comment(1)
It seems to me that the differences between versions by cosmin and abourget are the order of parents in merge commits. A good history visualization tool (e.g. gitk) should be able to render both histories identically. The only obviously missing thing is the branch hg/stable in the version by abourget. I guess it's the thing between named branches, unamed branches and bookmarks in Mercurial.Seduction
G
0

Two-way hg-git (and git-git, hg-hg) sync is also possible with the service Git-hg Mirror. It uses hg-git (among others) behind the scenes and its code is also open source.


Disclaimer: I'm from the company behind it.

Gland answered 30/4, 2017 at 16:36 Comment(0)
V
0

The up-to-date answer in 2021 seems to be git cinnabar, which is used e.g. by Firefox.

Other scripts suggested on this page are either unmaintained or require outdated software to run (typically python 2.7). By contrast, cinnabar works with python 3.5+ and is maintained until the date of writing at least.

Once cinnabar installed, you can either clone mercurial repositories directly by prefixing with hg:::

git clone hg::https://hg.mozilla.org/mozilla-unified

Or add or set a remote to

git remote set-url origin hg::https://hg.mozilla.org/mozilla-unified
git fetch origin

You can push to mercurial remotes.

Using hg2git and git2hg commands allow to translate git commit sha1s to mercurial changeset and back. More docs available on the github page.

Vraisemblance answered 17/10, 2021 at 6:59 Comment(8)
git cinnabar does not work either. It seems to have no support for supplying hg credentials or for working with largefiles.Proptosis
Maybe not fully feature @user7860670, but I couldn’t get any of the other options to even run.Vraisemblance
felipec/git-remote-hg does run.Aquilar
@Aquilar you might have fixed it since and the most upvoted answer here still points to your repo, but at the time of writing this answer it definitely didn’t.Vraisemblance
@Vraisemblance Did you file a bug report?Aquilar
@Aquilar looking at your commit history the issue is described in my post: at the time of writing, running git-remote-hg required python 2. I’m not sure a (possibly duplicated) “please support python 3” issue would have been useful.Vraisemblance
Mercurial for most of its history required python2, it wasn't only around 2021 that it finally worked with python3. At the time you wrote your comment it hadn't even had a year working. It would have been sensible to just use python2 for git-remote-hg.Aquilar
Python 2 was end-of-life since beginning of 2020, with a quite generous 12 years notice, so I don’t think using python2 in 2021 is sensible, no. But it’s a good thing people finally catch on.Vraisemblance

© 2022 - 2024 — McMap. All rights reserved.