git-filter-repo
Rewrite repository history to filter content
TLDR
Replace a sensitive string in all files
Extract a single folder, keeping history
Remove a single folder, keeping history
Move everything from sub-folder one level up
SYNOPSIS
git filter-repo [--help | --version] [options] [--] [pathspecs...]
PARAMETERS
--analyze
Analyze repo usage instead of rewriting; outputs stats on paths/blobs.
--analyze-paths [path]
Analyze paths reaching certain size/commit thresholds.
--path path
Rewrite history to remove/keep exact path from all commits.
--path-glob glob
Like --path but matches glob patterns (shell-style).
--invert-paths
Invert meaning of --path/--path-glob (keep non-matching).
--replace-text expressions.txt
Redact text in blobs matching regexes from file; repeatable.
--replace-text-expressions file
Like --replace-text but loads Python expressions.
--blob-callback pycode
Python callback to filter/modify individual blobs.
--tree-callback pycode
Python callback to filter/modify tree objects.
--commit-callback pycode
Python callback to filter/modify commits.
--tag-callback pycode
Python callback to filter/modify annotated tags.
--message-callback pycode
Python callback to edit commit messages.
--refname-callback pycode
Python callback to rename refs.
--strip-blobs-bigger-than size
Remove blobs larger than given size (e.g., 10M).
--max-pack-size size
Split packs larger than size during rewrite.
--force
Overwrite backup refs even if exist.
--dry-run
Print actions without rewriting.
--debug [--debug]
Enable debug output; repeat for more verbosity.
--quiet
Suppress non-error output.
--refs ref
Rewrite only specified refs; repeatable.
--all-refs
Rewrite all refs, including notes and reflog.
DESCRIPTION
git filter-repo is a versatile, high-performance tool for rewriting Git repository history. It supersedes the slow and error-prone git filter-branch, providing 10-1000x speedups and safer operations. Use it to remove files from history (e.g., credentials, large binaries), rename/move paths, redact sensitive text across blobs, split or squash repositories, or apply custom Python callbacks to commits/trees/tags.
Key strengths include automatic backup cleanup (reflogs, original refs), support for partial rewrites (specific refs or paths), dry-run previews, and analysis modes (--analyze). It processes commits sequentially, applying filters to blobs, trees, and metadata while preserving Git invariants. For path-based filtering, specify --path or --path-glob; for text redaction, use --replace-text with regex files. Advanced users leverage callbacks like --blob-callback for logic in Python.
Best practice: clone fresh before use (git clone --no-local --mirror <repo>). Output is a new history; push with git push --force. Endorsed by Git project for production history surgery.
CAVEATS
Destructive: rewrites history irreversibly; always clone fresh repo first. Not for bare/public repos without backups. Requires Python 3.5+ and Git 2.22+. Callbacks must be valid Python; test dry-run. No support for grafts/shallow clones.
INSTALLATION
Download from https://github.com/newren/git-filter-repo: git clone https://github.com/newren/git-filter-repo; cd git-filter-repo; ./git-filter-repo. Or pip3 install git-filter-repo.
EXAMPLE
Remove file: git filter-repo --path path/to/secrets.txt --invert-paths.
Redact passwords: Create redact.txt with (?i)password[\s]*=[\s]*[^\n]+; git filter-repo --replace-text redact.txt.
HISTORY
Created 2018-2019 by Elijah Newren to replace git filter-branch. First public release 2019; Git docs recommend it since v2.24. Actively maintained on GitHub (newren/git-filter-repo); 100+ contributors.


