Git filter-repo: The Official Replacement for filter-branch

The Git project now officially recommends git-filter-repo over the legacy git filter-branch. This single-file Python script (requires Python 3.6+ and Git 2.36.0+) handles history rewriting tasks that were previously painful or impossible.

Why filter-repo?

git filter-branch is "extremely to unusably slow" and "riddled with gotchas that can silently corrupt your rewrite." The Git project states these issues cannot be fixed backward compatibly. git-filter-repo is multiple orders of magnitude faster, safer, and far more capable.

Simple Example: Extract a Subdirectory

Suppose you want to extract the src/ directory into a new repository, rename all files to live under my-module/, and prefix tags with my-module-. With filter-repo, it's one command:

git filter-repo --path src/ --to-subdirectory-filter my-module --tag-rename '':'my-module-'

Compare this to filter-branch, which requires a multi-step, error-prone pipeline:

git filter-branch \
  --tree-filter 'mkdir -p my-module && git ls-files | grep -v ^src/ | xargs git rm -f -q && ls -d * | grep -v my-module | xargs -I files mv files my-module/' \
  --tag-name-filter 'echo "my-module-$(cat)"' \
  --prune-empty -- --all
git clone file://$(pwd) newcopy
cd newcopy
git for-each-ref --format="delete %(refname)" refs/tags/ | grep -v refs/tags/my-module- | git update-ref --stdin
git gc --prune=now

Even the faster --index-filter variant is still clunky and OS-specific. The BFG Repo Cleaner cannot handle this kind of rewrite at all.

Design Rationale

git-filter-repo was built because no existing tool met the author's needs. It provides:

  • --analyze: Analyze your repo before rewriting, helping you decide what to prune.
  • --path and --path-rename: Keep or rename specific paths, instead of only removing.
  • Performance: Uses git fast-export/git fast-import internally, avoiding the overhead of filter-branch's shell-based approach.
  • Safety: Automatically handles edge cases like special characters in filenames and preserves empty commits intentionally.

Installation

Just place the git-filter-repo script into your $PATH. For advanced usage (e.g., using it as a Python module), see INSTALL.md.

What the Git Project Says

The Git project officially recommends git-filter-repo over filter-branch. They provide cheat sheets for converting filter-branch and BFG commands to filter-repo. For those attached to the old tools, filter-lamely (a.k.a. filter-branch-ish) and bfg-ish are reimplementations based on filter-repo that are more performant.

Bottom Line

If you're still using git filter-branch or BFG, switch now. git-filter-repo is faster, safer, and officially endorsed. The one-command example above should convince you: history rewriting no longer needs to be painful.