HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
newren
git-filter-repo
Python2019–2026
newren / git-filter-repo

git-filter-repo

Quickly rewrite git repository history (filter-branch replacement)

23Distinct people
27Mentions
2Explicit recommenders
13.5KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Quickly rewrite git repository history (filter-branch replacement)

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

I recommend using https://github.com/newren/git-filter-repo instead of filter-branch.

oftenwrong used a recommendation phrase. 3 indexed comments match. This is a phrase match, not a verdict.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year27 dated mentions

Observed mentions: 2019-08-21 19:43:04 UTC to 2026-10-01 17:48:53 UTC.

02462019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 1 mentions; 1 submissions, 0 comments20192020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 4 mentions; 1 submissions, 3 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 6 mentions; 0 submissions, 6 comments20222023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 4 mentions; 1 submissions, 3 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments2026-01-01 00:00:00 UTC to 2027-01-01 00:00:00 UTC (exclusive): 4 mentions; 1 submissions, 3 comments. Incomplete calendar period.2026*

* An incomplete calendar period is marked with an outlined bar. Its count is not directly comparable with a full period.

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC110
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC413
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC202
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC606
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC404
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC413
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC211
2026 (partial)2026-01-01 00:00:00 UTC2027-01-01 00:00:00 UTC413

What Hacker News says

27 sources
> Also Bend's stars came on the V1 launch. This is V2. It already had 20k before. This is the reason you should not reomve your commit history. How would anyone know that there were V1, and it was already popular? If you need to remove sensitive data, you should use tools like git-filter-repo. - https://docs.github.com/en/authentication/keeping-your-accou... - https://github.com/newren/git-filter-repo
In Bend – a language that blocks AI mistakes via proof and runs on GPUs
This is great! And how did I not know about this? My favorite days are when I learn something new. Even better are when I learn that I was wrong and change my mind to improve my thinking. So meta! Git notes would be ideal for annotating commits that contain commit hashes used as breadcrumbs to inform the developer (usually me months later) about context around previous work. These hashes might have changed due to a rebase or from using disk space optimization tools that rewrite history like these: https://rtyley.github.io/bfg-repo-cleaner/ https://github.com/rtyley/bfg-repo-cleaner https://github.com/newren/git-filter-repo https://github.com/tiavision/GitRewrite See also: https://stackoverflow.com/questions/5613345/how-to-shrink-th... https://stackoverflow.com/questions/1398919/make-git-consume... https://stackoverflow.com/questions/21167
Read the rest
78/reduce-git-repos... https://stackoverflow.com/questions/3119850/is-there-a-way-t... https://stackoverflow.com/questions/38789265/git-delete-some... https://stackoverflow.com/questions/16057391/git-free-disk-s... https://stackoverflow.com/questions/31423525/how-to-reduce-d... https://stackoverflow.com/questions/16854425/compact-reposit... https://stackoverflow.com/questions/13999191/trimming-huge-g... https://stackoverflow.com/questions/4515580/how-do-i-remove-... These methods are all uniquely terrible in various ways. Most likely user error on my part. I need this technique: 1. Choose a range of commit hashes (or hashes before a commit) and remove them. This can be useful when splitting repos, for example on projects that started as backend+frontend where the frontend is being forked off in a new repo and the older backend portion needs to be removed from it for security/privacy. 2. Rebase all branches (including those that crossed the deleted portion) to preserve their structure but start/end as recently as possible. Optionally discard branches that were created and merged entirely within the deleted ported, unless they're the trunk of other branches that merge after the deleted portion. 3. Search for old commit hashes in commit messages and update them to the new hashes while rebasing. 4. Bonus points for updating stashes (or other git features) having any commit hashes in their names. Also for importing/exporting a list of important commit hashes for use in project management, such as updating hashes in comments on kanban boards like Jira. 5. More bonus points for searching for large files (such as app.js or other build artifacts) so that they can be stripped from commits in branches, preferably not on a main trunk like master. If you followed this far, I could also use a technique that rebases merged branches so that they form a series of D shapes instead of overlapping B shapes (this is useful during git bisect). Ideally this would happen automatically or be enforced via rules on sites like GitHub and GitLab. I always rebase my branches before merging, but others can't be bothered. https://www.atlassian.com/git/tutorials/merging-vs-rebasing Where I'm going with this: I git reset and git cherry-pick constantly in my own branches before merging, so that each branch has a clean work history like the trunk. I think of this as quantum committing, because I keep exploring the problem space until I find a solution that collapses (merges) into the history. The problem is that git GUIs are inadequate for this work. I need to be able to cut/copy/paste commits, drag and drop them for reordering, etc. It should also derive the commit diff needed to make a commit match a branch (or folder) rather than throwing a conflict in my face, so that it operates more like Apple's Time Machine. If I had this app, I could simply select all commits that I wanted to delete, it would ask me "this rewrites history, are you sure?", and then delete them and do the right thing for affected branches. It would also have infinite undo powered by git reflog. The idea being that commit hashes should not take priority - it's all about the information. We should never be trapped by the state of the repo, because that creates anxiety. So we're missing a tool to orchestrate git the way that Kubernetes orchestrates Docker.
In Git Notes: Git's coolest, most unloved­ feature (2022)
I'd first check whether `git fsck` gives you more information. There isn't a simple and fast way to find parent objects, but here is a slow hack: git_find_references() { if [ "$#" -ne 1 ] || [ "${1#-}" != "$1" ]; then echo "usage: git_find_references <HASH>" >&2; return 1 fi local target="$1" git cat-file --batch-check --batch-all-objects --unordered | while read -r hash type size; do if [ "$type" != "blob" ] && git cat-file -p "$hash" | grep -F -q "$target"; then printf "%s %s\n" "$hash" "$type" fi done } # example: git_find_references 1cae71a9d5b24991c0d632b45186ca8a250e5d52 This will output the hashes and types of the objects that refer to the target. (The command is similar to the one posted by @Den
Read the rest
vercoder9, but is slightly more sophisticated.) Note that this function will be very slow on large repositories. I can't think of a way to make it faster without writing actual code. (My only tip is that you can search for multiple targets at once by changing the grep command to `grep -E -q "$target"` and then using `git_find_references "HASH1|HASH2|HASH3"`.) Once you find the referring objects, you can use `git cat-file -p <hash>` on them to see their content, and you can repeatedly invoke this function to walk up a directory tree until you get to the enclosing commit. --- To actually fix the corruption, you have a couple of options: - If the corruption is in a branch that you don't care about, just delete the branch. - Find a good copy of the object, e.g. from another repository (you said the object did not appear, but I just want to point out that you should check using `git cat-file -p <hash>` rather than by looking in .git/objects/, because objects can also be stored in packs). Or you might be able to work out what the content was (if the corrupt object is a blob, aka file, you might be able to work out the content based on the previous and next versions of that file; `git hash-object <file>` will tell you if it's exactly right, but won't give you any hints if it's slightly wrong). - Rewrite the history to remove/replace the corrupt object. You can use a tool such as `git-filter-repo` (docs: https://htmlpreview.github.io/?https://github.com/newren/git..., in particular see --strip-blobs-with-ids). You can also use `git replace` to temporarily replace the corrupt object with a placeholder; it won't fix the commit history, but it might be useful if the corruption causes commands to fail.
In In a Git repository, where do your files live?
this is great! I used to delete the entire repo and make a new one to get around accidentally checking in something huge. But it does give: WARNING: git-filter-branch has a glut of gotchas generating mangled history rewrites. Hit Ctrl-C before proceeding to abort, then use an alternative filtering tool such as 'git filter-repo' (https://github.com/newren/git-filter-repo/) instead. See the filter-branch manual page for more details; to squelch this warning, set FILTER_BRANCH_SQUELCH_WARNING=1. So the other option is: git filter-repo --invert-paths --path path/to/file
In Show HW: Removed large file from Git (and history too)
Regarding git filter-branch, that big warning does point you to try git filter-repo [1] instead. In my experience, every case that I've need git filter-branch for (or BFG for a bit) has been handled easily and well (including performance-wise) by git filter-repo. Don't let the fact that it needs Python and is still a separate download from the git suite (in part because it needs Python and that is not otherwise a git suite dependency) dissuade you from using an easier and faster alternative to git filter-branch. [1] https://github.com/newren/git-filter-repo
In Git commands you probably do not need
The problem is that outside of those five or six commands, Git gets really hard REALLY FAST. Let's use a common scenario as an example. Let's say someone accidentally committed a password into your codebase six months ago and pushed to remote. You can't delete just that commit because Git is a graph, so you have to modify the parent commit that contains the password _and every other commit after it_. So you discover `git filter-branch` which runs a shell script against matching SHAs. You run `man git-filter-branch` or `git filter-branch --help` but discover that (a) it can use special environment variables, none of which are documented here, (b) you notice that there are different types of filters, i.e. `env-filter`, `index-filter`, `tree-filter`, all of which require intimate knowledge of how Git works to use it. (I train junior engineer
Read the rest
s on Git often. Once you mention the "staging area" and "index", you'll usually lose them. I can't blame them...they just want to track their work!) You then try to run a `git filter-branch` command with the `--index-filter` since this can work against individual SHAs. Immediately, you get this: $: git filter-branch --index-filter '' WARNING: git-filter-branch has a glut of gotchas generating mangled history rewrites. Hit Ctrl-C before proceeding to abort, then use an alternative filtering tool such as 'git filter-repo' (https://github.com/newren/git-filter-repo/) instead. See the filter-branch manual page for more details; to squelch this warning, set FILTER_BRANCH_SQUELCH_WARNING=1. And then it just _hangs._ Since you know that going through six months of history can take a while, you think that it's working in the background. Nope, it just hangs there, waiting for you to CTRL-C instead of exiting with a non-zero exit code like EVERY OTHER CLI IN EXISTENCE. You go back into the `man` page to better understand this warning. Surprise surprise, `FILTER_BRANCH_SQUELCH_WARNING` isn't documented! So you provide the environment variable (if you know how, which isn't a given for junior engineers) and it finally runs...except you have no idea whether commits were rewritten or not (it does tell you whether the commits were rewritten, but you kind-of have to understand Git to understand the message). Now let's say you actually powered through and got it to run...but it caused you to lose work! (Remember, you have to `git push --force` or `git push --force-with-lease` to apply your changes, so this is stupid dangerous already, but it must be done.) To get it back, you then need to learn about `git reflog` and `git reset --hard`, but since `git filter-branch` runs against every commit that matched your pattern, you have to spend time scrolling back at the reflog to find the one you want to reset to. `bfg` exists to make this "simpler," but (a) it's a Java application, and you need to install the JRE to make it work, and (b) IT DOESN'T COME WITH GIT. Again, since this is a really common use-case with Git, it would be really nice if `git` had something more user-friendly, like: `git remove-references-to --regexp "PASSWORD" SHA_PATTERN` and a convenient message after the deed is done, like: 85 commits rewritten; run "git reset --hard [SHA_BEFORE_THE_CHANGES]" to undo. (Note: You must run `git push --force-with-lease to sync changes with your HTTPS-backed remote, "NAME_OF_REMOTE") However, since Git is maintained primarily for Linux development (afaict), this would most likely have to come from a third-party Git CLI. (I can already feel the rage from Linus for a proposal like this.) Funny enough, making things easier against the desires of protocol/system maintainers is how decentralized systems eventually centralize. I can see a world where everyone uses `gh` instead of `git` or has `git` aliased to `gh`, which means that a single company has de-facto control over the future of Git...
In Git making me want to pull my hair out yet again

Showing the 15 most recent of 27 sources. Enable JavaScript to search and browse every indexed mention.

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.