Skip to main content
This page contains examples from real users who have filed issues or questions about git-filter-repo. These scenarios demonstrate practical solutions to common and uncommon repository filtering challenges.

Adding Files to Root Commits

Add a LICENSE file and .gitignore to the very first commit(s) in history:
The insert-beginning script is available in the contrib/filter-repo-demos/ directory.

Purging a Large List of Files

When you have many files to remove, create a text file with one path per line:
Create deletion list
Remove files

Extracting a Library from a Repo

Keep a subdirectory but rename it to a higher-level directory:
This is useful when splitting a monorepo or extracting a component that you want to become standalone.

Replace Words in Commit Messages

Replace “stuff” with “task” in all commit messages:
For more complex replacements using regex:

Keep Files from Specific Branches Only

Delete all files except those currently present on two specific branches:

Renormalize Line Endings

Convert all line endings and add a .gitattributes file:

Remove Trailing Whitespace

Remove all spaces at the end of lines, including converting CRLF to LF:

Complex Include/Exclude Rules

Include all files under src/ except src/README.md:
This pattern is useful when you need both inclusion and exclusion logic that can’t be expressed with simple --path arguments.

Removing Paths by Extension

Removing a Specific Directory

Converting NFD Filenames to NFC

Mac systems use NFD (decomposed) Unicode normalization, which can cause issues. Convert to NFC (composed):

Set Committer for Recent Commits

Change the committer of the last 5 commits:

Handling Special Characters in Names

When dealing with names containing accents, umlauts, or other multi-byte characters:
Python doesn’t allow multi-byte characters directly in bytestrings, so use .encode() to convert from a Unicode string.

Handling Repository Corruption

Corrupt Commit Objects

If git fsck reports corrupt commits:
Check for corruption
Fix corrupt commit

Corrupt Tree Objects

For corrupt trees with duplicate entries:
Fix corrupt tree
Create replacements for all corrupt objects before running git filter-repo.

Removing Files with Backslashes

Remove any file with a backslash in its path (common issue from Windows):

Replace a Binary Blob in History

Replace a sensitive image file throughout history:

Remove Old History (Commits Older Than N Days)

This changes every commit hash and permanently discards history. Only use if you’re certain this is what you want.
The git replace --graft command with no parent arguments converts ${OLD_COMMIT} into a root commit, effectively removing all its parents from history.

Replacing PNGs with Compressed Versions

If you committed large PNGs and later compressed them, you can retroactively use the compressed versions:
Identify blob IDs
This shows output like:
Replace old with new

Updating Submodule Hashes

If wrong submodule commit hashes were recorded, you can fix them:
blob_id is somewhat of a misnomer here since the file’s hash actually refers to a commit from the sub-project, but that’s the parameter name used by --file-info-callback.

Using Multi-line Strings in Callbacks

When callbacks add spaces at the front of every line, use textwrap.dedent:
Without dedent (incorrect)
With dedent (correct)