Resurrecting Deleted Items

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.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset