git-filter-repo
The supported way to remove a file, a secret or a path from every commit in a repository.
What it does
git-filter-repo rewrites history: drop a path from all commits, extract a subdirectory into its own repository, rewrite author emails, strip files over a size threshold, or scrub a leaked credential.
git filter-repo --path secrets.env --invert-paths
git filter-repo --strip-blobs-bigger-than 10M
git filter-repo --subdirectory-filter docs
git filter-repo --email-callback 'return b"new@example.com"'It is the tool Git’s own documentation now recommends in place of git filter-branch, which was orders of magnitude slower and easy to get subtly wrong.
This rewrites every commit hash from the filter point onward. Every clone becomes incompatible and must be re-cloned, and the rewrite has to be force-pushed — which a protected branch will refuse. Run it on a fresh clone, and for a leaked secret treat the credential as compromised and rotate it: rewriting history does not un-publish what was already fetched or cached.
Alternative to
| Alternative | Type | Trade-off |
|---|---|---|
| BFG Repo-Cleaner | Open source | Faster for the narrow cases it covers, Java-based |
git filter-branch | — | Deprecated, orders of magnitude slower and easy to get wrong |
| Starting a fresh repository | — | Sometimes genuinely cheaper than rewriting a decade of history |
Install
brew install git-filter-repo