Motivation
I have been using Mercurial for my private projects since 2014, together with TortoiseHg as frontend. Back then, Microsoft was still favoring TFS for Visual Studio integration. Over the last years this has changed, at latest with the aquisition of GitHub, Visual Studio integration for git nowadays is as good if not even better than TFS.
November 2022 I decided to work with git on my private projects in the future. I like the integration in Visual Studio and there are no real alternatives for using Mercurial in the same way as git. Furthermore, most online DVCS hosters focus on git while Mercurial support is the exception.
Of course I wanted to keep my revision logs from the last 8 years and convert the Mercurial repositories to git repos. After some research I found this blog entry from Mark Heath, that describes a way doing this from a Windows PC. Unfortunately, it’s not working exactly as described in this blog post anymore – given the fact, this post is from 2013 (maybe I should have picked git directly back then…), it’s no wonder things don’t work like they did 10 years ago. I also was unknowingly using a TortoiseHg version where the hg-git extension was not bundled.
Fortunately, there are some other resources, that provide the necessary tips and alterations needed to get it working. The main work for me to do was to put it all together into the right steps. With updating alexpage.de to a new theme I decided to publish my approach as a guide and revisited all the steps I did last November. I hope this post is of help for all people, who are trying to do the same hg to git conversion on a Windows PC.
Sources
My starting point:
https://markheath.net/post/how-to-convert-mercurial-repository-to
Necessary alterations I needed to make on my PC:
https://stackoverflow.com/questions/67859068/tortoisehg-mercurial-can-not-find-hggit-extension
https://foss.heptapod.net/mercurial/tortoisehg/thg/-/issues/5707#note_156800
Additional information or alternatives I found while writing this post:
https://til.secretgeek.net/mercurial/convert_hg_to_git.html
https://helgeklein.com/blog/converting-mercurial-repositories-to-git-on-windows/
Prerequisites
To setup a bare git repository we later need as a conversion target, an installation of git is required. You can download git for Windows here, if you don’t have it installed already:
https://git-scm.com/download/win
If you have used Mercurial before, you probably have it installed somewhere, most likely like me together with TortoiseHg. If not, you can get the recent version of Mercurial together with TortoiseHg here:
https://www.mercurial-scm.org/downloads
I recommend installing the latest versions of Mercurial and git. Some versions of TortoiseHg did not bundle the required hg-git extension (https://stackoverflow.com/questions/67859068/tortoisehg-mercurial-can-not-find-hggit-extension), but the current version of (6.4.5) seems to have it included.
Both git and hg need to be in your PATH environment variable. Check this after having installed any missing tool by opening a command line (cmd.exe will do the job) and just type:
PATH
You should find your install folders both tools somewhere in the console output.
A quick notice on directory (folder) names: I will be describing the working directory from where the commands are run in the following steps. I assume as a developer you have have a basic knowledge on how to work with the command line (changing directories with cd, path names in general, slashes/backslashes on Linux/Windows).
Conversion
Activating the hg-git extension
To make use of the hg-git extension, it needs to be activated. This can be done by just adding the following lines to the mercurial.ini. The file is located directly in your Windows user directory (C:\Users\YourUserName). If you have TortoiseHg installed, you can edit the file from “File>TortoiseHG Settings>Extensions” or activate the extension directly with the checkbox. In the end, you mercurial.ini should contain this:
[extensions]
hggit =
In contrast to Mark’s blog post, the path to hg-git seems not to be required anymore. After saving the mercurial.ini file, do a quick check for active mercurial extensions. Just enter from any directory:
hg help
The section for active extensions is a little bit hard to find, as it’s located between the commands and the additional help topics, but if everything is correct so far you should see this line somewhere in the output:
hggit push and pull from a Git server
Creating the bare git target repo
The next steps are more or less identical to Mark’s instructions. After having all the necessary tools configured, we can move on to setting up our new git repo. This needs to be a new bare git repo, so we cd to our working directory (D:\scm\blog in our example), where we want to have the bare git repo created and create it with:
git init --bare test01.git -b main
The ouput should be like:
Initialized empty Git repository in D:/scm/blog/test01.git/
For further information on git default branch please read https://github.blog/2020-07-27-highlights-from-git-2-28/#introducing-init-defaultbranch. For this tutorial, we will go with the new “main” naming convention, so we actively name the default branch with the -b parameter.
Preparing the git repo
hg-git utilizes the hg bookmarks function to mark a branch for conversion. Make sure you have your Mercurial repo changes committed/merged to your default branch and your active branch in your Mercurial directory is the default branch. In your Mercurial directory you can check this with:
hg summary
From your Mercurial repo directory add a bookmark named “hg” with:
hg bookmarks hg
After having set the bookmark, check the summary of your Mercurial repo again. The default branch should have the hg bookmark now. The bookmark will become the target branch name in our new bare git repo, when we push from Mercurial to git in the next step.
A way to convert more than one branch to git is described here: https://til.secretgeek.net/mercurial/convert_hg_to_git.html
Please be aware that this tutorial uses different bookmark and branch names.
Pushing the Mercurial repo to the bare git repo
The next step does the actual conversion. We are pushing from our Mercurial repo to the bare git repo. From the directory of your Mercurial repo push with:
hg push d:\scm\blog\test01.git
Copying from hg branch to main branch
If you take a look at the newly filled bare git repo, you will notice, that it just contains a branch named hg. To finalize our git repo, we have to created the main branch (or master, if you chose so on creating your bare git repo) and copy our hg branch into the new main branch. To do so we run in our new bare git repo directory:
git branch main hg
git branch
This shows our two branches as a result:
hg
* main
Cloning bare git repo to a working repo
To check if everything was converted correctly and continue our work with our new git repository, we need to clone the bare git repo into a working tree. From the working directory run:
git clone test01.git test01_git
Change to the working tree directory (test01_git) and check the files with:
git status
The output should be similar to this:
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
If everything is ok, you can delete the hg branch from your bare git repo and and continue to work with you main branch from there.
Conclusion
Converting from Mercurial to git is not that difficult, if you have hg-git installed correctly and follow the right steps. Unfortunately sometimes you have to dig through older guides and stackoverflow posts first to find a working procedure. After having successfully converted my projects, I hope you find this guide helpful. Nevertheless, my thanks to the developers of hg-git and all contibutors to the sources I used to put this guide together. If you find any errors in this guide or have additions or feedback, feel free to use the comment function.
Nice clear tutorial, thank you.
When I get to the key step of hg push, I get this error:
** Unknown exception encountered with possibly-broken third-party extension “hggit” 1.0.2 (dulwich 0.21.3)
** which supports versions 6.4 of Mercurial.
** Please disable “hggit” and try your action again.
Which Mercurial version have you been using? I re-followed the steps with version 6.4.5, but did not encounter this error. I also tried to accidently do some mistakes or leave a step, but nothing led to this error message.