7

I have a new job however they use mercurial as their version control and most of my experience is with git. I try to learn mercurial but the way it does branching (even with extensions like bookmarks) just make absolutely no sense to me. Does anyone know of a way to use git locally but push to mercurial?

I have tried the hg-git plugin and have gotten to the point where I can commit in git and push those changes to a remote mercurial repo however the issue I am running into is that no matter what tutorial I have found, I can't seem to pull new changes from mercurial back into git (which makes the entire thing useless at this point). If you have a link on how to setup hg-git to work pushing to mercurial, please let me know of it.

The Solution (I think)

Base on the comments made by Lazy Badger, this is what I think will work : http://ryanzec.com/index.php/blog/details/9

Roman
  • 19,581
  • 6
  • 68
  • 84
ryanzec
  • 27,284
  • 38
  • 112
  • 169
  • 6
    Or you could just learn mercurial! – msarchet Oct 25 '11 at 20:59
  • 2
    Using git so long, I have come to use a certain workflow that is perfect for me and mercurial just does not support that workflow (at least it does not seems to after a few hours looking over mercurial). Learning mercurial right now is the last option (ie, if I can't figure out a way to use git, I will use my first day on the job to learn Mercurial). – ryanzec Oct 25 '11 at 21:05
  • 4
    Strongly recommend learning hg. I've used hg and git at work and they're really similar for 80% of the use cases. – Matt Ball Oct 25 '11 at 21:06
  • 2
    Learn Mercurial and be glad your company isn't using CVS (like mine) – Paul S Oct 25 '11 at 22:06
  • 1
    @ryanzec Could you describe your workflow, so that we could see if it can find a match in the Hg world? – gizmo Oct 26 '11 at 09:26
  • @gizmo Biggest issues after diving into mercurial is branches/bookmarks. I create branches consistently so I don't want to use named branches since you can't delete them (often I will create a branch and end up deleted it without merging). I heard bookmarks are hg's "git branches" but that is not true. If I make a commit to a bookmark that was created from the default branch, both the bookmark and branch record the commit which is not want I want. Named branches seems to be the only way to do what I normal do but not being able to completely delete them (not just close them) is an issue. – ryanzec Oct 27 '11 at 18:21
  • 1
    @ryanzec While I fail to understand why you anyonem would want to avoid creating branches (named or anonymous), you can still easily remove branches you don't want anymore using the 'strip' command from the MQ core extension. – gizmo Oct 28 '11 at 09:44
  • @gizmo I was unaware of that. I was told you can only close a named branch but if I can remove it, that changes things a little. I assume that strip-backup file are not automatically push to remote repositories when I push specifying -r – ryanzec Oct 28 '11 at 09:57
  • @ryanzec Indeed. strip-backup files are just regular hg bundles stored in your repository in case you made a mistake so that you can re-apply them. They are never pushed. – gizmo Oct 28 '11 at 10:00
  • @gizmo Ok, so here's what I did : hg branch topic1; #edited file; hg ci; hg update default; hg merge topic1; hg ci; hg strip topic1; : and after stripping topic1, the commit I merged from topic1 was removed from default. This is not what I want. This is was I excepted from my experience with hg and why I didn't think using named branches was going to be good. Git I do : git checkout -b topic1 master; git commit; git checkout master; git merge topic1; git branch -d topic1; : and after deleting topic1, the commits merged from topic1 are still in master. This is the workflow I am looking for. – ryanzec Oct 28 '11 at 13:05
  • @ryanzec Ok, so what you want to do is not remove branches, but rebase them. So use the rebase extension. However, in the Hg world, it is generally considered as a bad practice, as it remove part of the history (the revision you started working on and the revision you merged back). This kind of information is helpful when a commit introduce a regression, in order to understand why the changes were done this way. – gizmo Oct 28 '11 at 13:35

3 Answers3

3

You can work with Mercurial end-point from git, but, unlike the inverse direction (hg -> git) you'll have to have both VCS and two repos on same location

  1. Install Mercurial
  2. Install hg-git extension for Mercurial
  3. Make sure you've enabled the Hg bookmark extension in your .hgrc
  4. Add to your .hgrc:

    [git]
    intree=1
    
  5. Clone your Mercurial repo

    hg clone ... repo
    
  6. Go to repo

    cd repo
    
  7. Create a local bookmark tracking your Mercurial default branch - this is what will be exported to your Git

    hg bookmark hg/default -r default
    
  8. Export to the git repo

    hg gexport
    
  9. Configure Hg to ignore the Git repo

    echo ".git" >> .hg/hgignore
    
  10. Configure Git to ignore the Hg repo

    echo ".hg*" >> .git/info/exclude
    
  11. Configure Git to ignore the same things as Mercurial

    git config core.excludesfile `pwd`/.hg/hgignore
    
  12. Have your master branch track the exported Hg default branch

    git branch --track master hg/default
    git reset --hard
    
  13. Work and commit to Git as usual

  14. Export your changes to Hg

    hg gimport
    
  15. Push all to the world

    hg push
    

For every-day-work repeat steps 13-15

PS: Work from HG to Git produces a lot less actions and headache

Sophie Alpert
  • 139,698
  • 36
  • 220
  • 238
Lazy Badger
  • 94,711
  • 9
  • 78
  • 110
  • First, at step 12, I have to reverse the order of the branches to : git branch --track master hg/default : but then when I try to do : git reset --hard : I get the error : fatal: This operation must be run in a work tree. If I do git init, then that error goes away but I am then in the same position where I can push change from git to hg but can't merge new change from hg back into git. – ryanzec Oct 26 '11 at 14:15
  • You miss one point probably - both repos are inside common WC, i.e all done in WC performed with **both** WC, you have to commit separately only. WC-merges follow this rule also. Sorry for 12, I wrote from memory – Lazy Badger Oct 26 '11 at 14:22
  • Not quite sure what you mean by that (assuming WC stands for Working Copy). I understand that this WC is both the WC for hg and git however I though with this workflow I would be able to work in git and then just have to do hg gexport and hg gimport to push and pull changes to and from hg and git. This setup does not even allow me to use any useful git commands because git does not think it is a work tree (like checkout commit, etc...). I am not sure what I am missing to make git actually work (unless I should be doing git init). – ryanzec Oct 26 '11 at 14:39
  • So do I create a bare/empty git repo and then follow these steps? so that I would create a empty repo at say /path/to/empty/git/repo and the do hg clone ... /path/to/empty/git/repo? – ryanzec Oct 26 '11 at 15:22
  • Yes. I *expect* that it should work that way, but testing of my *dirty idea* and probably fixing still **needed** – Lazy Badger Oct 26 '11 at 15:36
  • how can I clone a hg repo into a folder that already has a git WC, it just errors out saying that "abort: destination 'test' is not empty"? – ryanzec Oct 26 '11 at 15:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/4532/discussion-between-ryanzec-and-lazy-badger) – ryanzec Oct 26 '11 at 15:45
3

Think some time, see alternative solution, same lopsided and crooked, but less pretentious (I hope) - 3 repos (2 Mercurial + 1 Git) in 3-tier architecture of chain

They have (local) names, used below:

  • Master (hg) - central Mercurial repo of company
  • Mediator (hg) - middleware for translating changesets, created as clone of Master
  • WorkHorse (git) - final workplace, empty at start

Mediator have setting almost identical (hg-git, bookmarks) to hg-repo from solution 1, except one detail in [paths] section of hgrc - will be two path in in: Master and WorkHorse in order to be able pull|push in both direction, with Master and WorkHorse

Workflow:

  • Mediator pull changes from Master, push to WorkHorse (changesets presented as is, without collapsing, contrary to solution 1)
  • All (almost? not sure about merges) work happens on WorkHorse
  • Mediator pull changes from WorkHorse, push to Master
Mischa Molhoek
  • 164
  • 1
  • 9
Lazy Badger
  • 94,711
  • 9
  • 78
  • 110
  • Is it correct to assume that the Master repo is the remote repo (generally on a different server), the Mediator repo is the local repo that has hg-git setup on it, and the WorkHorse repo is the local repo that is completely git (and is linked to the Mediator repo)? If so, how do I get the Mediator repo to pull in the changesets from the Master repo in the way that when I update from the WorkHorse repo, git pulls in the changesets as is (unlike in the previous solution)? – ryanzec Oct 27 '11 at 18:14
  • Master is company repo, maybe in any place, you can haven't any *special* access to it (outside push/pull). Mediator is **your personal repo**, which you can create where you want and where you can configure it. WorkHorse, yes, is your workplace with Git. NB: all above and above above is just dirty idea, debug needed anyway. WorkHorse haven't any setting, which relate it to Mediator- it's Mediator's mission to push into WorkHorse pulled from Master changeset -and they will be transmitted as-is – Lazy Badger Oct 27 '11 at 18:24
  • Then how would I get the Mediator to push the changesets as-is to the WorkHorse that it pulls from Master? And wouldn't I have to create my WorkHorse by using git to clone from the Mediator repo? – ryanzec Oct 27 '11 at 20:16
  • You (on Mediator) just `push WorkHorse - because WorkHorse is a mirror of Mediator without latest pull-from-Master changesets, push will push only new data. Yes, you must create at WorkHorse git repo. But I see, you can't clone hg repo from git, thus - initial fill will be also push from Mediator to empty WorkHorse – Lazy Badger Oct 28 '11 at 00:01
  • What command would I use to push from Mediator to WorkHorse, that is the part I am a little confused on. – ryanzec Oct 28 '11 at 12:07
  • Thinking about it more, I think I know exactly where you are going with this. I am going to have to give what I think you are talking about a try. – ryanzec Oct 28 '11 at 14:01
  • I think you need to add in a second local git repo to the mix and then you basically can use hg-git as intended. You still need some ugly workarounds when setting it up but after that, it should be pretty smooth in working in both git and hg. I need to play with it but if it works, I will probably be writing a long blog post about it soon. – ryanzec Oct 28 '11 at 15:28
  • push from from Mediator to WorkHorse is the same command (and action in result) as push from from Mediator to Master: hg push WorkHorse (there you have WorkHorse defined in hgrc of Mediator repository). Can't see **obvious reasons** (but they *may be*) for additional git-repo-in-the-middle – Lazy Badger Oct 29 '11 at 00:28
  • There are some issues without having the repo-in-the-middle I am detailing in a blog post I will be posting shortly. – ryanzec Oct 30 '11 at 00:41
1

Nowadays, there is a new git-remote-hg extension that does what you need. It seems to be the counterpart to Hg-Git plugin. See http://felipec.wordpress.com/2012/11/13/git-remote-hg-bzr-2/

andref
  • 750
  • 5
  • 20
  • 1
    Unfortunately, it is unmaintained these days, and incomaptible with Mercurial 3.2 or later, but my fork still works: https://github.com/fingolfin/git-remote-hg – Max Horn Feb 09 '16 at 17:45