git-filter-repo. We’ll show you how to convert your existing commands and understand the key differences between the tools.
Quick Reference
BFG and filter-repo have different architectures:- BFG: Operates directly on Git tree objects using file basenames
- filter-repo: Operates on fast-export stream using full file paths
BFG expects the repository path as a final argument (
java -jar bfg.jar ... my-repo.git), while filter-repo expects you to cd into the repository first.Half-Hearted Conversions
You can quickly convert most BFG commands by replacingjava -jar bfg.jar with bfg-ish:
- BFG
- bfg-ish
bfg-ish provides bug fixes and features on top of BFG, but native filter-repo commands offer more capabilities and flexibility.
Key Differences
Path Handling
BFG operates on basenames only:- Cannot distinguish
README.mdin root vs. subdirectory - Cannot rename files or directories
- Limited to basename-based filtering
- Precise control over specific files at any path
- Supports file and directory renaming
- Enables complex restructuring operations
Object Handling
BFG directly manipulates tree objects:- Issues with loose vs. packed objects
- Doesn’t understand replace refs or grafts
- Limited index and working tree handling
- Automatic handling of packed/loose objects and refs
- Built-in support for replace refs and grafts
- Proper index and working tree updates
- Automatic garbage collection
Protection & Privacy Defaults
BFG’s “protection” and “privacy” defaults have been intentionally excluded from filter-repo:Command Conversions
Stripping Large Blobs
Remove files larger than a specified size:- BFG
- filter-repo
Deleting Specific Files
Remove files by name:- BFG
- filter-repo
The
--use-base-name flag makes filter-repo behave like BFG by matching against file basenames instead of full paths.Removing Sensitive Content
Replace passwords and secrets using a replacement file:- BFG
- filter-repo
The
--replace-text feature was originally created by BFG and implemented in filter-repo with better documentation. filter-repo’s docs provide more detail on the file format.Regex Replacement Difference
- BFG passwords.txt
- filter-repo passwords.txt
The bfg-ish script automatically translates
$1, $2 to \1, \2 for compatibility.Removing Files and Folders by Name
Remove all files/folders with a specific name throughout history:- BFG
- filter-repo
About the glob pattern:
--path-glob '*/.git'matches.gitdirectories one or more levels deep- Uses Git-style globs, not shell-style globs
--path .gitadded separately to catch top-level.git(since the glob has/)
Understanding Path Patterns
Since filter-repo uses full paths, you have more control but need to be more specific:Match by Basename (BFG-style)
- Match anywhere
- Specific path
Using Globs
- Subdirectories
- All levels
- Extensions
Feature Comparison
What BFG Does That filter-repo Doesn’t
Protection Features (Intentionally Excluded)
BFG’s HEAD protection and privacy footers have been excluded from filter-repo:
- No HEAD protection: Filters apply everywhere for consistency
- No Former-commit-id: Use replace refs instead
- No .REMOVED.git-id files: Cleaner history without artifacts
What filter-repo Does That BFG Doesn’t
Path-Based Operations
- Rename files and directories
- Move files between paths
- Filter by full path, not just basename
- Complex directory restructuring
Advanced Filtering
- Python callbacks for custom logic
- Commit message rewriting
- Author/committer updates
- Partial history rewrites
Better Integration
- Replace refs and grafts support
- Index and working tree updates
- Automatic garbage collection
- Packed/loose object handling
Safety Features
- Refuses to run on dirty repos
- Creates backups by default
- Validates before execution
- Better error messages
Migration Patterns
Common BFG Use Case: Clean Secrets
- BFG Workflow
- filter-repo Workflow
filter-repo automatically handles garbage collection, so no manual cleanup commands needed!
Common BFG Use Case: Extract Subdirectory
- BFG
- filter-repo
Migration Tips
Testing Your Migration
-
Clone first: Always work on a fresh clone
-
Test the command: Run filter-repo with
--dry-runif testing -
Verify results: Check that sensitive data is gone
Understanding the Output
filter-repo provides detailed statistics after completion:Force Pushing After Migration
Post-Migration Checklist
When to Use Each Tool
Use filter-repo when:
- You need path-based filtering (rename, move files)
- You want automatic cleanup and optimization
- You need Python callbacks for complex logic
- You want better Git integration
Use bfg-ish when:
- You have existing BFG commands to maintain
- You only need basename filtering
- You prefer BFG’s command syntax
Use BFG when:
- You specifically need JVM-based tooling
- You have complex Scala-based customizations
Next Steps
Cookbook
Common filtering patterns and recipes
Path Filtering
Master path-based filtering techniques
Content Filtering
Learn to filter by file content
API Reference
Python callbacks for advanced usage
