Removing data from source control
Remove specific data from source control
Deleting is not removing
A git rm followed by a commit removes the file from the current tree, not from history. Every earlier commit still contains it, every clone still has it, and anyone can retrieve it.
That distinction is the whole objective — and it is why the first question is never "how do I delete this?" but "what is it?".
Two very different cases
| Case | Action |
|---|---|
| A secret | Rotate the credential first. Removal is secondary |
| A large binary bloating the repository | Rewrite history to reclaim space |
For a committed secret, rewriting history does not undo exposure: the value has been distributed to every clone, fork, cache, CI log and backup that fetched it. Treat it as compromised, rotate it, and only then consider cleaning history. Doing the removal first and skipping the rotation is the failure that matters, because it feels like a fix.
Rewriting history
Tools such as git filter-repo (the maintained successor to filter-branch) and BFG rewrite commits to excise content. Consequences:
- Every commit hash changes from the rewrite point onward.
- Everyone must re-clone; existing clones cannot be reconciled.
- Open pull requests and existing tags may need recreating.
So it is a coordinated operation, not a quiet cleanup — schedule it, tell everyone, and expect forks and mirrors to retain the old objects unless they are handled too.
Prevention
Push protection stops the secret entering history in the first place, and .gitignore plus pre-commit hooks keep large artefacts out. Every one of those is cheaper than a history rewrite.
Primary sources