Reputation: 7386
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.
Upvotes: 25
Views: 13465
Reputation: 39606
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.
Upvotes: 30
Reputation: 44746
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.
Upvotes: 7