The great thing about version control systems is that information is never lost. Even when you
delete a file or directory, it may be gone from the HEAD
revision, but the object still exists in
earlier revisions. One of the most common questions new users ask is,
“How do I get my old file or directory back?”
The first step is to define exactly which item you’re trying to resurrect. Here’s a useful metaphor: you can think of every object in the repository as existing in a sort of two-dimensional coordinate system. The first coordinate is a particular revision tree, and the second coordinate is a path within that tree. So, every version of your file or directory can be defined by a specific coordinate pair. (Remember the “peg revision” syntax—foo.c@224—mentioned back in Peg and Operative Revisions.)
First, you might need to use svn
log to discover the exact coordinate pair you wish to resurrect.
A good strategy is to run svn log --verbose
in a
directory that used to contain your deleted item. The
--verbose
(-v
) option shows a list of all changed items in each revision; all
you need to do is find the revision in which you deleted the file or
directory. You can do this visually, or by using another tool to examine
the log output (via grep, or perhaps
via an incremental search in an editor):
$ cd parent-dir $ svn log -v ... ------------------------------------------------------------------------ r808 | joe | 2003-12-26 14:29:40 -0600 (Fri, 26 Dec 2003) | 3 lines Changed paths: D /calc/trunk/real.c M /calc/trunk/integer.c Added fast fourier transform functions to integer.c. Removed real.c because code now in double.c. ...
In the example, we’re assuming that you’re looking for a deleted file real.c. By looking through the logs of a parent directory, you’ve spotted that this file was deleted in revision 808. Therefore, the last version of the file to exist was in the revision right before that. Conclusion: you want to resurrect the path /calc/trunk/real.c from revision 807.
That was the hard part—the research. Now that you know what you want to restore, you have two different choices.
One option is to use svn merge
to apply revision 808 “in reverse.” (We
already discussed how to undo changes in Undoing Changes.) This would have the
effect of re-adding real.c as a
local modification. The file would be scheduled for addition, and after
a commit, the file would again exist in HEAD
.
In this particular example, however, this is probably not the best strategy. Reverse-applying revision 808 would not only schedule real.c for addition, but the log message indicates that it would also undo certain changes to integer.c, which you don’t want. Certainly, you could reverse-merge revision 808 and then svn revert the local modifications to integer.c, but this technique doesn’t scale well. What if 90 files were changed in revision 808?
A second, more targeted strategy is not to use svn merge at all, but rather to use the svn copy command. Simply copy the exact revision and path “coordinate pair” from the repository to your working copy:
$ svn copy http://svn.example.com/repos/calc/trunk/real.c@807 ./real.c $ svn status A + real.c $ svn commit -m "Resurrected real.c from revision 807, /calc/trunk/real.c." Adding real.c Transmitting file data . Committed revision 1390.
The plus sign in the status output indicates that the item isn’t merely scheduled for addition, but scheduled for addition “with history.” Subversion remembers where it was copied from. In the future, running svn log on this file will traverse back through the file’s resurrection and through all the history it had prior to revision 807. In other words, this new real.c isn’t really new; it’s a direct descendant of the original, deleted file. This is usually considered a good and useful thing. If, however, you wanted to resurrect the file without maintaining a historical link to the old file, this technique works just as well:
$ svn cat http://svn.example.com/repos/calc/trunk/real.c@807 > ./real.c $ svn add real.c A real.c $ svn commit -m "Re-created real.c from revision 807." Adding real.c Transmitting file data . Committed revision 1390.
Although our example shows us resurrecting a file, note that these same techniques work just as well for resurrecting deleted directories. Also note that a resurrection doesn’t have to happen in your working copy—it can happen entirely in the repository:
$ svn copy http://svn.example.com/repos/calc/trunk/real.c@807 http://svn.example.com/repos/calc/trunk/ -m "Resurrect real.c from revision 807." Committed revision 1390. $ svn update A real.c Updated to revision 1390.