LinuxCommandLibrary

git-filter-repo

Rewrite repository history to filter content

TLDR

Replace a sensitive string in all files

$ git filter-repo --replace-text <(echo '[find]==>[replacement]')
copy

Extract a single folder, keeping history
$ git filter-repo --path [path/to/folder]
copy

Remove a single folder, keeping history
$ git filter-repo --path [path/to/folder] --invert-paths
copy

Move everything from sub-folder one level up
$ git filter-repo --path-rename [path/to/folder]/:
copy

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.

SEE ALSO

git filter-branch(1), git(1)

Copied to clipboard