By Hugo Sereno Ferreira


2009-05-19 15:26:51 8 Comments

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?

10 comments

@Piedone 2017-04-30 16:36:23

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.

@dubiousjim 2012-06-24 15:31:43

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.

  2. 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.

  3. 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.

  4. 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.

  5. 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:

@dubiousjim 2012-08-04 12:24:17

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.

@dubiousjim 2013-06-14 15:08:09

There's also Kiln Harmony.

@CAD bloke 2013-06-16 22:06:40

Yup. Kiln Harmony is awesome. Free for solo devs too.

@FelipeC 2012-11-13 02:52:03

There's a new git-remote-hg 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.

@Antoine Pelisse 2013-04-18 13:37:44

Hey Felipe, that's not exactly true, you need a working version of mercurial as a dependency

@schmmd 2013-05-23 20:08:02

Make sure you name it exactly git-remote-hg (i.e. no .py suffix).

@Clayton Stanley 2013-09-15 23:32:18

Works when the hg repository is a submodule as well.

@FelipeC 2013-10-01 04:20:40

@Artjorn That's probably coming from another git-remote-hg that is distributed by msysgit, you need to remove that script.

@Kevin Cox 2013-12-12 23:19:02

Note that you need python 2. So if python 3 is the default on your system (or if you don't run Debian and want to be future proof) change the first line to #!/usr/bin/env python2.

@Cimbali 2015-10-04 14:38:03

Note that since Mercurial 3.2 @FelipeC 's git-remote-hg does not work anymore (github.com/felipec/git-remote-hg/issues/27) that is, until the fork that fixes the issue is merged (see github.com/fingolfin/git-remote-hg)

@code_dredd 2016-01-11 03:59:17

There's a fork of the original repository at https://github.com/fingolfin/git-remote-hg that fixes the issue. I can confirm it works. My test was done with Git v2.5.0 and Mercurial 3.4. I don't expect the original author to come back to life to merge the patch.

@FelipeC 2016-01-12 22:36:10

I will, if the patch makes sense. But not right now.

@code_dredd 2016-01-12 22:55:48

@FelipeC: Feel free to take your time and not merge the bug fix. Given that this issue was reported back in Nov. 2014 (no repo updates since Aug 2014), I saw (and based on your comment, still see) no reason to expect the merge. I'm just glad that someone else already fixed it and I can use that instead.

@FelipeC 2016-01-14 01:24:01

I do this in my own free time, so yeah, I will take my time. If the Git community actually cared about this, they would not have removed it from the core, but they don't care. So.

@Isochronous 2016-03-03 22:34:05

Not everyone in the git community (most people, in fact) has any say in that decision.

@FelipeC 2016-03-04 00:12:57

Maybe. But nobody voiced any concerns either.

@code_dredd 2016-05-03 07:42:50

@FelipeC: I think you should reconsider the "nobody voiced any concerns" remark, especially in light of the fact that this highly up-voted question exists with a highly up-voted answer and another repository with the issue already properly addressed is available, to say the least. But hey, I'm glad others don't go around playing that kind of game.

@FelipeC 2016-05-05 03:44:49

"We" here in StackOverflow are irrelevant. "We" have absolutely no say in what happens to the Git program.

@FelipeC 2016-06-04 19:42:07

BTW. The compatibility issue has been fixed for a while now.

@Darius M. 2017-04-22 21:22:01

@AntoinePelisse: You're right, just install it via pip install mercurial.

@weynhamz 2014-01-01 17:51:27

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.

@Mikko Rantalainen 2014-04-10 11:37:46

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.

@Mikko Rantalainen 2012-06-27 09:59:04

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.

@dubiousjim 2012-06-30 21:09:59

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.

@Mikko Rantalainen 2012-07-02 09:52:06

@dubiousjim 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.

@dubiousjim 2012-07-02 13:07:30

Too bad, I thought there might be some way to use push successfully that I wasn't seeing.

@matt wilkie 2013-02-01 20:18:22

+1 for highlighting the impedance mismatch and what to look for

@Abderrahim Kitouni 2009-07-06 21:06:31

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.

@Christian Oudard 2009-12-15 15:32:08

don't forget to run easy_install hg-git first

@Hugo Sereno Ferreira 2009-12-18 16:38:12

Not exactly what I wanted, but still doable. Thanks.

@Rocky Burt 2011-04-12 14:12:51

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.

@yesudeep 2011-07-25 21:15:32

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 you

@yesudeep 2011-07-25 21:23:22

See blog.vucica.net/2011/05/… for more information.

@rich.e 2011-08-26 03:53:21

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.

@rich.e 2011-08-26 03:54:48

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.

@ThaDon 2011-10-22 20:39:42

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?

@ryanzec 2011-10-26 14:45:53

@ThaDon I am get the same exact issue and also trying to figure out how to get it to work

@ThaDon 2011-11-14 16:22:35

What I ended up dong @ryanzec is popping open my .git/config file and removing bare=true and that seemed to solve things

@mb14 2011-11-20 22:21:18

@ThaDon I have the same problem. Apparently the git repo is created as .hg/git. The solution is to 'ln -s .hg/git .git'.

@akaihola 2012-09-04 11:40:21

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.

@Martin Geisler 2009-05-20 21:34:06

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

@Wizz 2011-08-04 06:45:39

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.

@David Given 2012-05-23 23:07:41

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...

@David Given 2012-05-24 18:09:47

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?

@Wizz 2012-05-25 09:12:28

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)

@David Given 2012-05-25 09:32:33

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.

@Mikko Rantalainen 2012-07-04 05:06:01

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?

@CAD bloke 2012-12-06 11:03:41

You could probably install and get the hang of Git in those 2 days you were waiting. ;)

@Wizz 2013-01-05 12:27:15

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 :)

@sykora 2009-05-19 15:39:10

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.

@reconbot 2010-06-20 20:27:33

This converted an hg repo into a git repo, thank you very much!

@Andrei 2011-09-27 14:01:11

This script failed for me, but the original hg-fast-export worked fine

@dubiousjim 2012-06-30 21:02:54

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.

@ralphtheninja 2009-05-19 15:32:52

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

@sykora 2009-05-19 15:36:19

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.

@dubiousjim 2012-06-30 21:04:43

@sykora, it can be used to drive interoperability from the reverse direction too. See some of the tools I list in my answer.

Related Questions

Sponsored Content

42 Answered Questions

[SOLVED] How do I revert a Git repository to a previous commit?

45 Answered Questions

[SOLVED] What is the difference between 'git pull' and 'git fetch'?

81 Answered Questions

[SOLVED] How do I undo the most recent local commits in Git?

33 Answered Questions

[SOLVED] How do I undo 'git add' before commit?

30 Answered Questions

[SOLVED] How do I check out a remote Git branch?

39 Answered Questions

[SOLVED] How do I delete a Git branch locally and remotely?

32 Answered Questions

[SOLVED] How do I rename a local Git branch?

  • 2011-07-06 03:20:36
  • Forrest
  • 2641157 View
  • 7983 Score
  • 32 Answer
  • Tags:   git git-branch

42 Answered Questions

[SOLVED] How do I force "git pull" to overwrite local files?

32 Answered Questions

[SOLVED] How can I reset or revert a file to a specific revision?

35 Answered Questions

[SOLVED] How to remove local (untracked) files from the current Git working tree

  • 2008-09-14 09:06:10
  • Readonly
  • 2132917 View
  • 6524 Score
  • 35 Answer
  • Tags:   git branch git-branch

Sponsored Content