Skip to main content
This guide is for users familiar with git filter-branch who want to migrate to git-filter-repo. We’ll show you how to convert your existing commands and take advantage of filter-repo’s improved performance and safety.

Quick Reference

filter-branch and filter-repo have different approaches:
  • filter-branch: Checks out each commit and runs shell commands on the working copy
  • filter-repo: Operates on the fast-export stream with predefined filters and Python callbacks
filter-repo defaults to rewriting all branches while filter-branch requires -- --all to do so. Use --refs <rev-list-args> to limit the scope in filter-repo.

Half-Hearted Conversions

You can quickly convert any git filter-branch command by replacing it with filter-lamely:
This approach runs faster but keeps most of filter-branch’s drawbacks. For best results, convert to native filter-repo commands as shown below.

Basic Differences

Default Scope

  • filter-branch: Operates on specified branches only (requires -- --all for everything)
  • filter-repo: Rewrites all refs by default (use --refs to limit scope)

Automatic Improvements

filter-repo automatically handles:
  • Rewriting old commit IDs in commit messages
  • Pruning commits that become empty
  • Running garbage collection after filtering
  • Shrinking repository size

Command Conversions

Removing a File

The filter-branch manual shows three variations of removing a file:

Extracting a Subdirectory

Move a subdirectory to the repository root:

Moving Tree into Subdirectory

Place all files into a new subdirectory:

Re-grafting History

Attach history to a different parent commit:
--proceed is required because filter-repo errors if no filtering arguments are specified.

Removing Commits by Author

This is a BAD example for both tools! It doesn’t remove the author’s changes, just their commits. The changes get attributed to subsequent authors. Use git rebase instead for most use cases. Learn more about the differences.

Rewriting Commit Messages

Removing Text

Remove git-svn-id lines from commit messages:

Adding Text

Add Acked-by lines to the last 10 commits:

Changing Author/Committer Info

Update email addresses throughout history:
Both filter-repo methods also update tagger emails, which filter-branch doesn’t handle.

Restricting to a Range

Filter only specific commit ranges:
Use ^C instead of --not C with filter-repo to avoid flag parsing issues.

Advanced Conversions

Running Code Formatters

Apply a code formatter to all matching files in history:
The lint-history script simplifies code formatting operations while maintaining filter-repo’s automatic handling of commit message rewrites and empty commit pruning.

Migration Tips

Performance

filter-repo is significantly faster than filter-branch, especially for large repositories:
  • No checkout overhead
  • Operates on fast-export stream
  • Efficient blob handling

Safety

filter-repo includes built-in safety features:
  • Refuses to run on repos with uncommitted changes
  • Creates backups by default
  • Validates operations before execution

Next Steps

  1. Test on a clone first: Always test migrations on a repository copy
  2. Review changes: Use git log and git diff to verify results
  3. Update remotes: After successful migration, force-push to update remote repositories
  4. Inform collaborators: Everyone needs to re-clone after history rewriting

Need More Examples?

See the Examples for common filtering patterns and advanced use cases.