Code‎ > ‎Tutorials‎ > ‎

Git + Mercurial HowTo


    How to use git on top of mercurial (for people who like git more than mercurial)

    Summary

    • Keep a git repository running on top of hg
    • Avoid hg pain
    • Keep hg history linear and work-in-progress-cruft-free
    • Keep a "master" branch in git that always and only reflects the state of hg tip, and work branches where changes take place.

    Setup

    1. hg clone http://foo/bar myrepo
    2. cd myrepo
    3. git init .
    4. git add * # if this is not a fresh checkout, be more selective - don't add build artifacts
    5. git add .gitignore .hgignore # and any other dot files you may find, BUT DO NOT ADD THE .hg DIRECTORY
    6. git commit -m 'initial commit'
    7. (sanity check - git status & hg status: both empty, git branch says you're on "master")

    Doing work

    1. git checkout -b <workbranch>
    2. work work work, git commit, make other branches, etc etc. BUT: never commit local changes to the "master" branch!

    Syncing

    1. git checkout master
    2. sanity check both hg status and git status show nothing.
    3. hg pull -u
    4. git add <new files> # if new files exist
    5. git commit -a -m '<helpful message about hg commits>'
    6. git checkout <workbranch>
    7. git merge master # merge

    Sending out a review

    1. git checkout <workbranch>
    2. hg addremove -s 25 # I find 25 to be a nice number for move detection
    3. ./request_codereview <params> (see submitting-code)
    Notes: it's always safe to keep running hg addremove to clobber previous addremove state. Corner case: you remove a file in a branch, then checkout another branch where the file is no longer removed. Just hg add the file again and it will clear up the glitch. To be certain, you can check out you rmaster branch, and verify hg status shows up with nothing. Then go back to your work branch and run addremove again, it should never do anything spurious after that.

    Committing

    1. Make sure you are up-to-date just before doing this, to ensure linear mercurial history and to avoid mercurial merges. Follow steps in "Syncing". Then, assuming you're in now a workbranch:
    2. hg addremove -s 25
    3. hg commit && hg push # hg status should then show nothing
    4. (sanity check - git status & hg status: both empty)
    5. git checkout master
    6. (sanity check - git status: empty; hg status: inverse of your change)
    7. git merge <workbranch>
    8. (sanity check - git status & hg status: both empty)
    9. git branch -d <workbranch> # use lower-case d. cleanup old branch.
    10. (optional git checkout <workbranch2>, git merge master, etc should all work cleanly). 
Comments