简体   繁体   中英

Delete all traces of a SVN commit

Someone in our team accidentally committed files containing a password to our repository. The password can't easily be changed.

Is there a way, with full admin permissions, to delete all traces of this commit? I'm not talking about a revert or delete, which would obviously keep the password in the file history.

Yes, but it is not for the faint of heart. You have to use svnadmin dump and svnadmin load to recreate your repository.

If you choose to do this, the first step is to stop your users from committing , and make a backup of your repository. I also recommend walking through the steps on a copy of your repository; you can use rsync to copy the entire repository directory into a temporary directory, and work from there.

For these instructions, I'm going to create a new repository in a temporary directory:

tmp, 502> svnadmin create example.repo
tmp, 503> svn co file://`pwd`/example.repo example
Checked out revision 0.

I created a file that contained four revisions, the 3rd of which needs to be deleted:

example, 536> svn log test.txt 
------------------------------------------------------------------------
r4 | kgregory | 2011-04-06 08:46:59 -0400 (Wed, 06 Apr 2011) | 1 line

post-bad commit
------------------------------------------------------------------------
r3 | kgregory | 2011-04-06 08:46:42 -0400 (Wed, 06 Apr 2011) | 1 line

bad revision
------------------------------------------------------------------------
r2 | kgregory | 2011-04-06 08:46:28 -0400 (Wed, 06 Apr 2011) | 1 line

good revision
------------------------------------------------------------------------
r1 | kgregory | 2011-04-06 08:46:02 -0400 (Wed, 06 Apr 2011) | 1 line

initial revision
------------------------------------------------------------------------

So, we need to dump revisions both before and after the bad one, using the -r flag to specify revision ranges. The --incremental flag on the second dump is important, because it will tell the load command not to create a new file.

Note that I'm running these commands from the same directory that holds the repository.

svnadmin dump -r 1:2 example.repo/ > pred.svndump
* Dumped revision 1.
* Dumped revision 2.
tmp, 552> svnadmin dump -r 4:4 --incremental example.repo/ > succ.svndump
* Dumped revision 4.

Now move the original repository out of the way, and create an empty repository with the same name:

tmp, 540> mv example.repo example.repo.bak
tmp, 541> svnadmin create example.repo

And import the contents of the dump files.

tmp, 569> svnadmin --quiet load example.repo < pred.svndump 
tmp, 570> svnadmin --quiet --ignore-uuid load example.repo < succ.svndump 

Now tell everyone to delete their working directories and check out fresh. And you should see the following log:

example, 574> svn log test.txt 
------------------------------------------------------------------------
r3 | kgregory | 2011-04-06 08:46:59 -0400 (Wed, 06 Apr 2011) | 1 line

post-bad commit
------------------------------------------------------------------------
r2 | kgregory | 2011-04-06 08:46:28 -0400 (Wed, 06 Apr 2011) | 1 line

good revision
------------------------------------------------------------------------
r1 | kgregory | 2011-04-06 08:46:02 -0400 (Wed, 06 Apr 2011) | 1 line

initial revision
------------------------------------------------------------------------

There is one HUGE caveat: this process assumes that there haven't been any commits to the file since the bad commit (ie, the successor dump only contains changes to other files).

If that's not the case, you can still delete the revision, but it's a lot more work. You need to create a new check-in, containing a clean copy of the file along with any other files that were changed with it while bad. Then create multiple dumpfiles, excluding any revisions that contained the bad file.

Finally: I strongly suggest several dry runs. As you can see from the history numbers in my examples, I screwed up a few times. As I said at the beginning, it's easy to copy a Subversion repository into a temporary directory. And when you do that, you can keep trying until you get it right, then just copy the fixed repository back into place.

See the answer at the FAQ

There are special cases where you might want to destroy all evidence of a file or commit. (Perhaps somebody accidentally committed a confidential document.) This isn't so easy, because Subversion is deliberately designed to never lose information. Revisions are immutable trees which build upon one another. Removing a revision from history would cause a domino effect, creating chaos in all subsequent revisions and possibly invalidating all working copies.

The project has plans, however, to someday implement an svnadmin obliterate command which would accomplish the task of permanently deleting information. (See issue 516.)

In the meantime, your only recourse is to svnadmin dump your repository, then pipe the dumpfile through svndumpfilter (excluding the bad path) into an svnadmin load command. See chapter 5 of the Subversion book for details about this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM