Recovering from a Bad Mercurial Subrepo State

Earlier today I was checking out a Mercurial repository I setup a while back as a blank template for projects. Unfortunately, my last commit to it was a merge that broke the subrepo state. It also suffered from a typo in the .hgsub file. In short, the repository was hosed because I couldn't update to any of the previous revisions. I kept getting errors like:

cloning subrepo vendor/_src/twig.js from git://github.com:justjohn/twig.js.git
fatal: unable to connect to github.com:
github.com: Servname not supported for ai_socktype

abort: git clone error 128 in vendor/_src/twig.js (in subrepo vendor/_src/twig.js)

and

abort: invalid subrepository revision specifier in .hgsubstate line 5

It took me a lot of searching to find a solution to these problems, so I'm documenting it here in the hope that someone else finds it useful.

Here are the steps I took to get the repository back into a usable state:

Clone the repository, but don't update to the latest revision (-U flag)

hg clone -U ssh://hg@bitbucket.org/justjohn/template

Revert to a (mostly) good revision excluding the subrepo directories (all were in vendor/_src, you might need multiple "-X" arguments). I was still seeing some errors after running this related to subrepos, but it recovered all the non-subrepo files in the repository.

hg revert -a -r 17 -X vendor/_src

Now, force set the parent revision for your working directory to the latest in the repository:

hg debugrebuildstate -r 19

Now, remove references to hgsub and hgsubstate and commit:

hg rm .hgsub
hg rm .hgsubstate

hg commit -m "Remove broken subrepo files"

You'll still be unable to update to the broken revisions prior to this, but you can at least clone the repository successfully now.