Mirror Git to Mercurial

June 17th 2020, 2:53 pm

Tired of Git absolutely destroying your work due to its garbage interface and dozens of built-in foot-guns? Need to use it to publish your code to GitHub? I keep a dual-repo of everything I work on locally so that I can do my real work in Mercurial but mirror manually to Git for publishing. Its a bit of a pain in the ass, but its less of a pain in the ass than having to use Git in any way other than adding commits and pushing to GitHub. If you find yourself in a situation where you want to dual-repo an existing personal project, here is a handy set of command-line instructions that you can run on Linux to make a commit-accurate (but not time-accurate) mirror of your Git repo in Mercurial. Note that this is for personal projects, so it will assume you're the committer on everything. But maybe it will help you like it helped me?

  • List out all commits from HEAD (make sure to "git checkout trunk" or similar first).
git rev-list HEAD --reverse > /tmp/hgimport

  • Init mercurial
hg init

  • Copy gitignore, format it for mercurial syntax, ignore git repo
echo -e "syntax: glob\n\n.git/\n.gitignore\n.gitattributes" | cat - .gitignore > .hgignore

  • Go through commit list, check out commit, clean the repo (delete removed/untracked files), add/remove those files, commit them with the git commit message.
for I in $(cat /tmp/hgimport) ; do git checkout $I ; git clean  -d  -fx --dry-run . | sed 's/Would remove //' | grep -v "\.hg" | xargs rm ; hg addremove . ; hg commit -m "$(git log --format=%B -n 1 .)" ; done

  • Clean up temp export
rm /tmp/hgimport

Once you run the above steps, you should be able to re-run "git checkout trunk" or similar and see that your Mercurial repository is clean. You will have untracked .hg/ and .hgignore files in your Git repo, but its easy enough to add them to your .gitignore in a commit. Once this is done, you can continue where you left off working in Mercurial. My preferred workflow is to get things to a point where I'm ready to publish, then one-by-one check out the Mercurial commits and commit them to Git so the history matches. Its not perfect, but it is virtually free of foot-guns and I haven't lost work yet in 3 years of doing this. Can't say the same about just using Git to do regular stuff.