Introduction
I prefer Mercurial (hg) to git. I don’t really have any reason for this preference - they both do the same thing, and the user experience for 90% of the use cases is the same. It probably comes from the conditions of the DVCS landscape when I started using these systems. Some of this may have been perception only, but it looked like this:
- GitHub didn’t have free private repos
- BitBucket did have free private repos
- BitBucket was very hg-friendly
- Joel Spolsky had an amazing tutorial that served as both a how-to for hg as well as a general intro to DVCS
- hg was much more Windows-friendly than git
- Since hg was written in python, I felt like extending it would be easier than doing so for git if I ever needed to (admittedly, this is a pretty ridiculous reason)
- hg felt like a more unified, “coherent” system than the very linux-y feeling git and its extensions (also pretty ridiculous)
- Where they differed, I liked the verbs hg used better than git’s counterparts
Nowadays, most of these are moot:
- Git has private repos
- Git for Windows is a thing, and I also love SourceTree
- Pretty much everybody else in the world uses git
Anyway, I still generally prefer using hg and hosting with BitBucket, so I have many (private) hg repos out there. Unfortunately, BitBucket is sunsetting support for Mercurial, so I have a lot of migrating to do.
Migration Tools
There are basically two ways to migrate a Mercurial repo to git:
- Use the hg-git Mercurial plugin to push an existing hg repo to a git repo
- Execute hg-fast-export against a local repo to export to create a git version of the repo in another local directory
I’ve used hg-git before; in general it works pretty well. But I’d need to install and configure it, or install TortoiseHg, and that didn’t sound appealing. On the other hand, hg-fast-export is a bash script, which requires a bash. The readme says On windows the bash that comes with "Git for Windows" is known to work well.
Well, I don’t use Git for Windows, so that didn’t sound very appealing either.
I thought, “maybe I should boot into Ubuntu and do all of this.” Wait… why not give Windows Subsystem for Linux a try?
Using WSL and hg-fast-export
Once I installed Windows Subsystem for Linux (note you have to run a PowerShell command to enable installation) with Ubuntu 18.04, I performed the following steps to prepare my system:
- Update all packages (
sudo apt update
) - Upgrade all packages (
sudo apt upgrade
) - Install Python 2.7 (
sudo apt install python
) - Install pip (
sudo apt install python-pip
) - Install Mercurial (
sudo pip install mercurial
) - Clone the hg-fast-export repo (
sudo git clone https://github.com/frej/fast-export.git
)
It’s important to note that I performed the last step after changing to the directory I wanted to clone to. WSL mounts your Windows drives and gives you access via /mnt
, so your entire C: drive is accessible under /mnt/c
, for example. My repos were in C:\repos
and I wanted to put the fast-export tool alongside them, so I did this:
cd /mnt/c/repos
mkdir hg-fast-export
cd hg-fast-export
sudo git clone https://github.com/frej/fast-export.git
With the tools I needed all set up, I converted a project in an hg repo named my-project
like this:
mkdir /mnt/c/repos/my-project-git
cd /mnt/c/repos/my-project-git
sudo git init
sudo ./../hg-fast-export/fast-export/hg-fast-export.sh -r ./../my-project
The result was some output like this:
master: Exporting full revision 1/75 with 35/0/0 added/changed/removed files
master: Exporting simple delta revision 2/75 with 0/4/2 added/changed/removed files
...
Skip .hgtags
master: Exporting simple delta revision 5/75 with 1/0/0 added/changed/removed files
develop: Exporting simple delta revision 6/75 with 0/0/0 added/changed/removed files
...
feature/authentication: Exporting simple delta revision 75/75 with 26/3/8 added/changed/removed files
Exporting tag [initial-setup] at [hg r2] [git :3]
Exporting tag [appharbor-build-and-deployment-working] at [hg r19] [git :20]
Issued 77 commands
/usr/lib/git-core/git-fast-import statistics:
---------------------------------------------------------------------
Alloc'd objects: 5000
Total objects: 689 ( 162 duplicates )
blobs : 331 ( 105 duplicates 227 deltas of 331 attempts)
trees : 283 ( 57 duplicates 191 deltas of 282 attempts)
commits: 75 ( 0 duplicates 0 deltas of 0 attempts)
tags : 0 ( 0 duplicates 0 deltas of 0 attempts)
Total branches: 10 ( 8 loads )
marks: 1024 ( 75 unique )
atoms: 202
Memory total: 2344 KiB
pools: 2110 KiB
objects: 234 KiB
---------------------------------------------------------------------
pack_report: getpagesize() = 4096
pack_report: core.packedGitWindowSize = 1073741824
pack_report: core.packedGitLimit = 35184372088832
pack_report: pack_used_ctr = 94
pack_report: pack_mmap_calls = 45
pack_report: pack_open_windows = 1 / 1
pack_report: pack_mapped = 732185 / 732185
---------------------------------------------------------------------
I followed this up with git checkout HEAD
. I examined the resulting git repo in SourceTree, and I have to say it looks like a good copy. I didn’t use any technical measure to verify the conversion. I could see that the default
branch from the hg repo was renamed master
in the git repo in accordance with convention. hg-fast-export allows you to customize the export process with plugins as well. More details are available on the github readme.
Overall, I found that the Windows Subsystem for Linux was an excellent way to use linux terminal tools to apply changes on a Windows system!
Comments