How do I fix a repository with one broken revision?

unwind picture unwind · Apr 4, 2011 · Viewed 44.1k times · Source

My home server had a hard drive failure.

Once I realized the disk was going, I logged in and did a straight copy of my repository, which contains multiple projects.

However, since the disk was failing, one of the revisions is broken:

$ svnadmin verify master/
[...]
* Verified revision 820.
* Verified revision 821.
* Verified revision 822.
svnadmin: No such revision 823

The master/db/revs/ and master/db/revprops/ directories do, indeed, not contain any files called 823, so this revision is missing (broken). There are subsequent revisions (that I really want to keep!) in the master/ repository going up to revision #947.

Today I fetched my most recent off-site backup (!), which happily includes this revision. I would like to "heal" the broken repository in master/ by fixing the missing revision, since it is more recent than the backup.

I made sure to load the dump file into a newly created repository with the same version as the copied one in master/, so it's all the old "linear" format 3.

I tried the obvious, to just copy the file 823 from the backup's db/revs/ and db/revprops/ directories:

$ cp repos/db/revs/0/823 master/db/revs/
$ cp repos/db/revprops/0/823 master/db/revprops/

The directory repos/ contains a repository that has been loaded from the backup dump. Now I get:

$ svnadmin verify master/
[...]
* Verified revision 821.
* Verified revision 822.
svnadmin: /build/buildd/subversion-1.6.12dfsg/subversion/libsvn_delta/compose_delta.c:165: search_offset_index: Assertion `offset < ndx->offs[ndx->length]' failed.
Aborted

Which is not very encouraging. I've tried various other svnadmin commands, but none have made the verifier happy.

My next idea was to back out the copying and start with a "fresh" copy of the broken repository, then dump out the revisions after 823, and merge with the backup. But that doesn't seem possible, I can't dump revisions after the missing one:

$ svnadmin dump -r 824 master/ >r824.dmp
svnadmin: No such revision 823

Note that it doesn't help to make the dump "incremental", in the hopes that it should pretend the world started with revision 824 and just go from there:

$ svnadmin dump --incremental -r 824:947 master/ > dump.txt
svnadmin: No such revision 823

This does write output to dump.txt, but I'm not sure if it can be relied upon. Note that it doesn't log that it successfully dumped any revision.

Update: I had another idea: to copy the newer revision files from the crashing-disk-copy in master/ into the backup, to provide the "missing tail":

$ for a in $(seq 910 947) ; do cp  master/db/revs/$a repos/db/revs ; cp master/db/revprops/$a repos/db/revprops/ ; echo $a ; done

However, this seems to do nothing but corrupt the target repository:

$ svnadmin verify repos/
[...]
* Verified revision 907.
* Verified revision 908.
* Verified revision 909.
svnadmin: Corrupt representation '907 21815 45 30922 158d3e72732f45bf6f02919b22fc899a'
svnadmin: Malformed representation header

Now, I've run out of ideas.

Answer

unwind picture unwind · Apr 8, 2011

I solved it.

The solution was (of course) obvious, once I realized it.

I had this:

  • master/: A copy of a broken repository, featuring revision 0..947, with revision 823's files physically missing.
  • repos/: A repository loaded from a backup (dump file), covering revision 0..910.

The solution was simply to dump from master/, from revision 911 and onwards. This was possible without any errors, which I take it means that none of the revisions in the range 911..947 directly depended on the state in revision 823, or something:

$ svnadmin dump --incremental -r 911:947 master/ > tail.txt
* Dumped revision 911.
* Dumped revision 912.
* Dumped revision 913.
[...]
* Dumped revision 947.

Anyway, then just apply the dump to the repository coming from the backup:

$ cat tail.txt | svnadmin load repos/
[lots of commits]

And now I have the full history restored, no problems:

$ svnadmin verify repos/
* Verified revision 0.
* Verified revision 1.
* Verified revision 2.
[...]
* Verified revision 945.
* Verified revision 946.
* Verified revision 947.

Yay!