Redacting a PDF Doesn't Erase It From Git History
Committing a redacted PDF over an older copy in a git repository feels like replacing a file. It isn't. Git keeps every version it has ever seen, by design, and "removing" a file in a new commit leaves the old blob sitting in history for anyone with access to the repository — or a clone of it — to check out.
Most of the version-control problems this site talks about involve cloud drives: Google Drive or SharePoint keeping an old revision in a panel most people never open. A git repository is a different animal entirely, and the people who hit this problem are usually engineers, not office workers. A developer redacts an API key, a customer record, or a credentials file out of a PDF — a support ticket export, a signed vendor agreement, a scanned invoice committed to a docs folder — replaces it in the repository, and assumes the job is done because the working tree now shows the clean version. The working tree is not the repository. The repository is the entire sequence of snapshots git has ever taken, and by default none of them are ever thrown away.
Why this is a different problem than "the old version is in a history panel"
Google Drive and SharePoint keep old revisions in one place: the service's own servers, under one account's or tenant's control. An administrator can, in principle, open a settings panel and purge them. Git has no equivalent single point of control. Every clone of a repository — on a teammate's laptop, on a CI runner, on a server, in a fork on GitHub or GitLab — is a complete, independent copy of the entire history, not a pointer back to one canonical store. The moment a commit containing the unredacted PDF is pushed anywhere and pulled once, there isn't one copy to clean up; there are as many copies as there are clones, and you may not have a list of all of them. That's a structurally harder problem than "ask Google Workspace support to purge a version," and it's the reason this deserves its own explanation rather than being folded into the cloud-storage version-history page.
What actually happens inside the repository
Git doesn't store files as a stack of diffs layered on a master copy. Each distinct version of a file's contents is saved as its own object, identified by a hash of that content, and a commit is really just a pointer to a tree of those objects plus a pointer to the commit before it. When you replace the PDF and commit, git creates a new object for the new bytes and a new commit that points to it — but the old object, and the old commit that pointed to it, don't go anywhere. They're still fully reachable by walking the commit history backward, which is exactly what `git log`, `git checkout <old-commit> -- path/to/file.pdf`, or simply opening an earlier revision in a hosting platform's web UI will do. Deleting the file in a later commit, or adding it to `.gitignore`, only changes what the current snapshot looks like going forward. It does not touch a single byte of what's already recorded in earlier commits, because rewriting commits that other history depends on is exactly what git's content-addressed design exists to make hard to do by accident.
That permanence is normally the point — it's what makes a repository trustworthy as a record of what changed and when. It becomes a liability the moment a committed file contained something that should never have been readable in the first place, because the same design that protects a project's history from accidental loss also protects your mistake from accidental loss.
A sequence that treats history, not just the working tree, as the thing to fix
Redact locally before the file is ever committed
Use the tool above on the PDF before it goes into the repository the first time. A file that was never committed unredacted has no history to clean up later — this step makes every step below unnecessary.
If it's already committed, stop treating a new commit as a fix
Committing a redacted replacement is still worth doing for the current snapshot, but say so explicitly to anyone relying on the repo: the old file is still in history until a separate rewrite happens. Don't let a clean working tree stand in for a clean repository.
Rewrite history with a tool built for it, not by hand
git filter-repo or the BFG Repo-Cleaner can strip a specific file or path out of every commit that ever touched it. Both rewrite commit hashes from that point forward — this is not something a normal commit or `git rm` accomplishes.
Force-push, then get every clone replaced, not just updated
A force-push changes the shared remote, but anyone who already cloned or forked the repository still has the old commits sitting on their own disk or account. They need to discard that clone and re-clone, or hard-reset past every rewritten commit — an ordinary pull or a stray push from an old clone can reintroduce the exact history you just rewrote.
How HidePDF fits into this
HidePDF only ever sees the PDF you drop into the tool on this page, processed in that browser tab. It has no integration with git, no way to inspect a repository, and no way to force-push or rewrite a commit on your behalf — that part of the problem is entirely outside what a browser-based file tool can reach. What it does do is produce the clean file that should be the only version that ever gets committed, which is the one step in this whole process that actually prevents the problem instead of cleaning up after it.
Mistakes and misconceptions that leave the old PDF reachable
"I deleted the file and committed, so it's gone." It's gone from the current snapshot, not from history. Anyone who runs `git log --all --full-history -- path/to/file.pdf` or opens the file's history in a hosting platform's UI can still find and restore the earlier commit.
"I made the repo private afterward, so it's covered now." Visibility is a setting on the current state of the hosting platform's account controls. It has no effect on clones or forks that already exist from when the repository was public — those copies kept everything they had at the time, independent of what the visibility setting says today.
"I force-pushed a rewritten history, so it's handled." A force-push only changes what the remote's default branch points to. Every teammate's existing local clone, every fork, and every CI cache still has the old commits until each of those copies is specifically discarded or reset — and any one of them pushing or syncing normally can bring the old history right back.
"It was only in a private repo with two collaborators, so the blast radius is small." Small is not zero. Both collaborators' laptops, any CI runner that checked out the branch, and any backup of either machine now have a full copy of that history, independent of how few people had "access" in the platform's permission sense.
"Adding the file to .gitignore after committing it once will keep it out of history." .gitignore only controls what git tracks going forward from an untracked state. A file that was already committed stays tracked and stays in history; ignoring it later changes nothing about the commits that already exist.
Related guides
Explore more ways to redact PDFs privately, or use the redaction tool above:
Frequently asked questions
Does deleting a file and committing again remove it from git history?
No. Deleting the file in your working tree and committing that change only tells git to stop tracking it going forward. The blob holding the old, unredacted PDF is still stored in every earlier commit that referenced it, and anyone with the repository's history can check out an old commit or revision and get the original file back. Removing a file from the current snapshot is not the same as removing it from history.
If I make the repository private after the fact, is the old file safe?
Flipping visibility controls who can open the repository from that point on. It does nothing to copies that already exist: anyone who cloned or forked the repository while it was public kept a full copy of its history on their own machine or account, independent of whatever you do to visibility afterward. Treat anything that was ever public as potentially copied, whether or not you can still see those copies.
What's the actual way to purge a file from git history?
Tools built for this, such as git filter-repo or the BFG Repo-Cleaner, rewrite every commit that touched the file, which changes the hash of that commit and every commit after it. You then have to force-push the rewritten history and get every collaborator to discard their old clone or hard-reset to the new one, because their existing copy still has the original commits and can reintroduce them with an ordinary push. It is a coordination problem as much as a technical one, and it only protects copies you can actually reach.
Can HidePDF reach into my git history or remove old commits?
No. HidePDF redacts whatever PDF file you load into the browser tool on this page; it has no connection to git, GitHub, GitLab, or any other hosting platform, and no way to rewrite, force-push, or delete anything in a repository. It can only hand you a clean file to commit instead of the original. Everything that happens to that file once it enters a repository is between you and your version-control tooling.