Update: It’s official, Mercurial is dead. The last hg stronghold has fallen:
We’ve decided to remove Mercurial support from Bitbucket Cloud and the API. Mercurial usage on Bitbucket is steadily declining, and the percentage of new Bitbucket users choosing Mercurial has fallen to less than 1%.
– Atlassian
Happy aliasing!
Original post from 2018-07-31
I recently went through some Mercurial to Git migrations. While stack overflow pretty much always has something to tell you, it never goes so smoothly in real life. Here’s my step-by-step guide including some random errors that you are bound to encounter.
Step 1 - fast-export
Get fast-export from https://github.com/frej/fast-export
Step 2 - upgrade Mercurial
Use pipenv for example to use the latest via clean install:
pipenv --two
pipenv shell
pipenv install mercurial
pipenv shell
Step 3 - encounter errors
Weird things may happen. Specially if you have a lot of history in the mercurial repository. Fear not, just strip a lot.
I encoutered the following:
master: Exporting simple delta revision 609/1718 with 0/1/0 added/changed/removed files
master: Exporting simple delta revision 610/1718 with 0/0/114 added/changed/removed files
master: Exporting simple delta revision 611/1718 with 15/0/0 added/changed/removed files
Traceback (most recent call last):
File "../../git/fast-export/hg-fast-export.py", line 550, in <module>
notes=options.notes,encoding=encoding,fn_encoding=fn_encoding,filter_contents=filter_contents))
File "../../git/fast-export/hg-fast-export.py", line 441, in hg2git
sob,brmap,hgtags,encoding,fn_encoding,filter_contents)
File "../../git/fast-export/hg-fast-export.py", line 262, in export_commit
export_file_contents(ctx,man,added,hgtags,fn_encoding,filter_contents)
File "../../git/fast-export/hg-fast-export.py", line 139, in export_file_contents
d=file_ctx.data()
File "/Users/margus/src/venvs/api-1ofvI4PQ/lib/python2.7/site-packages/mercurial/context.py", line 1088, in data
return self._filelog.read(self._filenode)
File "/Users/margus/src/venvs/api-1ofvI4PQ/lib/python2.7/site-packages/mercurial/util.py", line 1437, in __get__
result = self.func(obj)
File "/Users/margus/src/venvs/api-1ofvI4PQ/lib/python2.7/site-packages/mercurial/context.py", line 702, in _filenode
return self._filelog.lookup(self._fileid)
File "/Users/margus/src/venvs/api-1ofvI4PQ/lib/python2.7/site-packages/mercurial/filelog.py", line 54, in lookup
return self._revlog.lookup(node)
File "/Users/margus/src/venvs/api-1ofvI4PQ/lib/python2.7/site-packages/mercurial/revlog.py", line 1501, in lookup
raise LookupError(id, self.indexfile, _('no match found'))
mercurial.error.LookupError: data/handlers/__init__.pyc.i@6f9b45217cdc: no match found
No matter how much I tried to delete all possible references to the file, this happened again and again. So I decided to strip history from around there instead.
Step 4 - strip history
Enable convert
extension in your hgrc
[extensions]
convert=
Pick your starting rev and shoot:
hg convert --config convert.hg.startrev=889 old-repo stripped-repo
Step 5 - fast-export, again
Hopefully you picked a good place, so the following goes without errors:
git init new-git-repo
cd new-git-repo
../fast-export/hg-fast-export.sh -r ../stripped-repo --force
git checkout HEAD
git remote add origin git@<your-upstream-url>
git push -u origin master
Pick your branches and push them as needed:
git branch --list
git push -u origin <branch-name>
Step 6 - cry a little
Mercurial is nice. But it has lost the race. Big platforms don’t support it, self hosting is pain and OSS has pretty much adapted Git as a standard. Have fun with configuring the hell out of you aliases now and reading through countless posts on how to actually use the beast. Like this three part guide which is missing the third part.. Well, resolving conflicts is hard.