Purge a file from git history
Removes a large file or committed secret from all git history with git filter-repo, with a backup first, exact commands, force-push coordination and what every collaborator must do.
Deleting a file in a new commit does not remove it from history: every clone, fork and cached view still has it. Removing it for real means rewriting every commit since it was added, which changes their hashes, invalidates open pull requests and breaks every collaborator's clone. git filter-repo is the tool the Git project recommends for this (git filter-branch is slow and error-prone, and BFG Repo-Cleaner is an older alternative). For a secret, the rewrite is cleanup, not the fix: anyone who cloned, forked or scraped the repository already has it, so the credential must be revoked and rotated first.
Write a step-by-step plan to remove this from the repository's entire history:
Hosting: Is a secret or sensitive data: Treat it as a secret even if this says false when the description shows a credential, token, key, private certificate or personal data, and say that you did.
- Before you start. If it is a secret, the first step is to revoke and rotate the credential and check its access logs for misuse, before touching history; say this plainly and do not let the rewrite delay it. For any rewrite: name the window when nobody may push, list the open pull requests and branches that will need recreating, check whether the file should instead stay in history through Git LFS (
git lfs migrate import --include="<pattern>" --everything) if it is a large asset the project still needs, and note that every commit hash after the first affected commit will change, breaking links and signatures on rewritten commits and tags. - Back up. A mirror clone (
git clone --mirror <url> backup.git) stored somewhere safe and access-controlled, because for a secret the backup contains it too; say when to delete the backup. - Rewrite. Install git filter-repo with the platform's package manager or pip, make a fresh mirror clone to work in, and give the exact command for this case:
- a path:
git filter-repo --invert-paths --path <path>(repeat--path, or use--path-globfor patterns); - large files by size:
git filter-repo --strip-blobs-bigger-than <size>, after listing the biggest blobs so the user can choose the threshold; - a secret string inside files that must stay:
git filter-repo --replace-text <expressions-file>, with the file format (literal:<secret>==>***REMOVED***orregex:<pattern>==>***REMOVED***) and a warning not to commit or share that file. For sensitive data, mention the--sensitive-data-removaloption that recent git filter-repo versions provide (it also fetches and rewrites refs such as pull request refs and reports the first changed commits) and tell the user to checkgit filter-repo --helpfor their version.
- Verify before pushing, with commands that must return nothing:
git log --all --oneline -- <path>for a path,git log --all -S '<secret>' --onelinefor a string (run it locally only and keep it out of shell history), and the largest-blobs listing again for size cleanups. Also check the tags. - Push. Re-add the remote if filter-repo removed it, temporarily allow force pushes on protected branches, then force-push all branches and tags (
git push --force --mirror originfrom the mirror clone, orgit push origin --force --allandgit push origin --force --tags). Explain that rejections of read-only refs such as pull request refs are expected on some hosts. Restore branch protection immediately afterwards. - Host cleanup for : the host still serves old commits through pull request refs, caches and forks. For GitHub, explain that pull request refs and cached views keep the old commits and that GitHub Support can remove cached views and run garbage collection on request, with the affected commit hashes; forks are separate repositories the owner must handle. For GitLab, use the Repository cleanup setting with the
commit-mapfile that filter-repo writes under.git/filter-repo/. For other hosts, say to check the host's documentation or support for purging unreachable objects. Also clear CI caches, artifacts and mirrors that may hold the old history. - Tell collaborators. Write the message to send: stop pushing; after the rewrite, re-clone (the safest option); anyone with unpushed work saves it as patches or rebases it onto the new history with
git rebase --onto, never merges an old branch, because that brings the purged file back; recreate open pull requests; delete old local clones and forks that contain the file. - Afterwards. Add the path or pattern to
.gitignore, add a pre-commit or server-side check (secret scanning or a file-size limit), and for a secret confirm the rotated credential works everywhere.
- Do not run any command yourself. Give commands for the user to run, and label each one read-only or rewrites history or force-pushes.
- Never print, echo or repeat the secret value in the plan; use a placeholder like
<secret>. - If it is a secret, rotation comes before every other step, and say that a history rewrite alone does not make the secret safe.
- Do not claim the data is gone from the host until the host cleanup step is done; say what may still hold it.
- If you are unsure an option exists in the user's tool version, say how to check instead of asserting it.
Before you start
Back up
Rewrite
Verify
Push
Host cleanup
Tell collaborators
Include the ready-to-send message in a quote block.
Afterwards
Each section uses numbered steps with commands in fenced blocks, each command labelled read-only, rewrites history or force-pushes.
1 required value still a placeholder; the assistant will ask for it.
details
- kind
- Prompt: a task you run by name to get one finished thing back
- domain
- Software engineering
- category
- Git and version control
- level
- Intermediate
- made for
- Open-source maintainer, Tech lead / staff engineer, DevOps / platform engineer, Software engineer
- risk
- read-only
- version
- v1.0.1 · incubating
- reviewed
- 2026-10-02
- works in
- Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Antigravity, OpenCode, Windsurf, Zed, Continue, AGENTS.md, ChatGPT, claude.ai
use in
npx @hermes-hq/hodios install purge-file-from-git-history --target claude-codenpx skills add hermes-hq/hodios-dist --skill purge-file-from-git-history -a claude-codeclaude plugin marketplace add hermes-hq/hodios-distclaude plugin install hodios-software-engineering@hodiosThe plugin brings every entry in this domain at once.
pairs well with
All of Git and version controlRespond to a leaked secret
Produces an ordered response plan for an exposed key, token or password - revoke and rotate, audit use, clean up copies, notify and prevent. Use right after a secret is committed, logged or shared.
respond-to-leaked-secretRecover lost Git work
Recovers commits, branches, stashes and staged files lost to a reset, rebase or dropped stash, using reflog and fsck after a backup, explaining each command. Use right after a git mistake.
recover-lost-git-workClean up a branch's commit history
Plans an interactive rebase that turns a messy branch into logical, reviewable commits, with a backup, the exact todo list and a check that the code is unchanged. Use before merging a WIP branch.
clean-up-commit-historyResolve a merge conflict
Resolves merge, rebase or cherry-pick conflicts by reading both sides and their common base, keeps the intent of each, and asks when the intents contradict. Use when git stops on a conflict.
resolve-merge-conflictWrite a commit message
Writes a commit message that states what changed and why, in the repo's own convention, and flags staged changes that should be split. Use before committing.
write-commit-messageWrite a pull request description
Writes a pull request description that tells reviewers why the change exists, what to look at first, how to test it and what could break. Use when opening a PR.
write-pr-description