Recovering a Deleted File from Subversion

Posted in Version Control on Wednesday, the 3rd of February, 2010.

This comes up every so often, and I always have to look up how to do it. So for future reference here's a quick howto on finding and recovering a previously deleted file from a Subversion repository. This assumes that you know roughly the name of the file, and roughly where it was in Subversion.

Locating the File

To start, you will need a working copy, otherwise known as a checkout, of the project. That's covered here. You can see the history of changes to a directory by cding into that directory and running svn log, but unfortunately that won't tell you anything about deleted files, so you need to use the --verbose switch:

svn log --verbose

That will probably give you far more information than you really care for, so it's useful to pipe the output to grep. Assuming that we're trying to track down a file named Esquilax.php, it should be simple enough to use grep to search for Esquilax.php in the output from svn log.

In this situation, it can be well worth using grep's -A and -B options, which give a bit of leading and trailing context to the output from the search. Five lines or so is often enough to find the revision in which the file was deleted, but you may need to experiment.

If you're fairly confident that the last thing you did with that file was delete it, which seems likely, a further useful tip is to use the -m or --max-count option. This option can be used to tell grep to stop searching after finding the first match (which will be the most recent commit involving your file). That should help filter out yet more noise. Here's the amended command:

svn log --verbose | grep -m1 -A5 -B5 Esquilax.php

The output will look similar to the following:

Added validation to input from the search form
r987 | simonh | 2009-06-19 10:17:17 +0100 (Fri, 19 Jun 2009) | 1 line
Changed paths:
D /path/to/application/Esquilax.php

Remove Esquilax.php, which we are no longer using
r955 | barts | 2009-06-17 15:37:25 +0100 (Wed, 17 Jun 2009) | 1 line
Changed paths:

Somewhere in the middle of that output we can see the all-important line:

D /path/to/application/Esquilax.php

This shows our file being deleted. Just below it is my commit message, and above it the number of the revision in which the file was deleted, in this case r987.

Recovering the File

Once we have the relevant revision number, recovering the file becomes nice and easy. Still working with our checkout, perhaps the simplest approach is to cd into the directory in which the file last lived and perform a reverse-merge against the offending revision:

[simonh@vps03 ~]$ cd /path/to/application/code
[simonh@vps03 application]$ svn merge -r 987:986 .
--- Reverse-merging r987 into '.':
A    Esquilax.php
[simonh@vps03 application]$ svn status
A  +    Esquilax.php

What we've done there is say "undo the changes to this directory that were made between revision 986 and 987, and give me a copy of the results". It's not unfeasible that you'll find other changes crop up, which you may have to revert manually. If anything, that's an argument for trying to make commits atomic, as discussed here.

Any changes that do occur as a result of this merge are uncommitted and thus fully reversible. If you do choose to commit the recovered file back to the repository, that's done just like any other commit. Happily, the file retains its history of changes, including those that were made prior to the deletion.


Posted by Eric P. on Monday, the 19th of April, 2010.

Clear, concise and just what I was looking for.

Eric P.

Posted by Malavika on Tuesday, the 24th of May, 2011.

Neat!!Just what i was looking for.

Enter your comment: