It has, very occasionally, been necessary to completely remove all traces of a file, or code, from the FreeBSD repository.
- Legally unencumbered. A developer commits a .o file from their working copy, or (worse) a core file.
- Legally encumbered. A developer commits some source code that their employer has not licensed for release to FreeBSD, or a developer commits a binary blob of firmware as part of a device driver.
When this happens it is necessary not only to revert the commit, but to ensure that the file or code is removed from all mirrors as well. This is especially important in the case of legally encumbered code.
Ideally this would also not invalidate any developer working copies checked in the time between the original commit and its removal.
One of the CVS repo-meisters has to hand-edit the appropriate ,v file to remove all traces of the commit. This change then flows to the downstream mirrors via CVSup.
XXX - The downstream mirrors do not need to be aware of this change, and the CVS command line tools will update checked out working copies as appropriate.
Obliterate is issue#516 in the Subversion issue tracker.
At this time Subversion does not formally have this functionality. There are various workarounds, but they assume that you have a single repository - or if you have downstream mirrors or replicas, then that you have control of them too.
The usual method is to dump the database and use a filter script to remove the offending material, then restoring the database. This is expensive but possible if necessary.
I've done some experiments. svndumpfilter(1) can remove complete files easily. Making it so that a delta "never happened" requires editing the dump file by hand to remove the sequence that adds the offending content then removes it in the subsequent commits. -Peter
Full obliteration is probably not possible with Hg as it uses SHA-1 chains to secure and link changesets. Partial obliterate is possible by careful (and mostly manual) intervention on the reference repository. As it is distributed, all users will have to be warned that their trees need to be cloned again with the new tree.
The Mercurial FAQ mentions this technique for obliterating files.
In a world where sha1s representing the entire state of the tree and history are so common, obliteration would have serious repercussions. However, you could choose to rewrite the history of a branch to obliterate a commit if you wanted:
git-rebase --onto bad-commit~1 bad-commit branchname
This says "take branchname, and replay all commits after bad-commit onto the commit just before bad-commit". Now bad-commit is gone and the sha1s for all of your commits since bad-commit have changed, since their parent's sha1 had changed.
Then you can push it with "git-push origin +branchname" where the '+' says that "yes, I know I just rewrote history but commit it anyway". Users who had the bad-commit already would need to say "git fetch +branchname" or "git fetch -f" to get the updated branch, as well.
Not Supported (yet) (also see monotone:FeatureObliterate)
The developers of Monotone recognize that this is not a feature used very often, but that when it's needed it's really needed and a few implementation method proposal are being discussed.
Right now committed data can be removed only from the last revision committed and only on a local database. Of course this can delete the last "n" committed revisions (one at a time), but the problem remains that nothing stops that data to be received back when sync'ing with a peer that still has it.
a crude but already working method would be to kill it in the described way and then force an epoch change, so that everybody must download the database anew (and the two epochs are assured not to conflict).