Sunday 15 November 2009

What to do when your Mercurial working directory got corrupted?

While performing a hg qrefresh today, I aborted the execution of the command because I added a wrong parameter. This resulted in a rather unfortunate situation:

$ hg status
mq status file refers to unknown node 30284bbd679b
mq status file refers to unknown node 30284bbd679b
abort: unknown revision '30284bbd679b7214334ec9a5eadbcb40d399f22f'!

Nothing would help, rolling back the aborted operation was not possible. After a bit of searching, I found Dealing With Repository And Dirstate Corruption. Apparently, my working directory suffered from dirstate corruption. According to http://www.selenic.com/pipermail/mercurial/2008-October/022069.html, which deals with the fact that MQ was involved as well, the fix is simple:

$ > .hg/patches/status
$ hg debugrebuildstate -r tip

This only takes a few seconds. Executing hg status after that took quite a while -- more than an hour in fact (it was the mozilla-central repo after all) -- but then my working directory state was recovered to the tip, and all operations on it could be performed again.

This does not actually change the tree, the changes applied to the code before were still present, so I didn't lose any work. Emptying .hg/patches/status also doesn't destroy your patch queue, it only makes MQ forget about which patches are currently applied.

Rebuilding the dirstate makes Mercurial forget about which files were added to the working directory though, so you have to hg add any files that you created yourself.

You are in a bit of trouble with MQ now unfortunately, because now you have changes in your working directory that are also partially covered by the patch (or patches) in your patch queue. You can't simply hg qrefresh, because MQ thinks there are no patches applied (remember, .hg/patches/status was cleaned).

Probably the easiest way forward is to save away the current state using hg diff > ../patches/backup.diff, hg revert the working directory, qpush all the patches back into the tree that were applied before the mishap, do an interdiff (Cygwin patchutils package for the Windows sufferers amongst you) between the backed-up diff and the output of hg qdiff, and then apply the output of the interdiff to the working directory.

I didn't go that route because I didn't really care about what was in my patch queue, so I just got rid of it and created a new queue.

No comments:

Post a Comment