Git
Version Control
Sensitive Data
Git History
Data Security

Remove sensitive files and their commits from Git history

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

If a secret file or sensitive data was committed to Git, deleting the file in a later commit is not enough. The sensitive content remains in the repository history until you rewrite that history and then coordinate cleanup with everyone who has a copy.

First Response: Rotate the Secret

Before touching Git history, rotate the exposed credential or secret if possible. History rewriting helps reduce future exposure, but it does not guarantee that nobody already copied the data from old clones, logs, caches, or forks.

That means the immediate response is usually:

  • revoke or rotate the secret
  • then clean the repository history
  • then prevent the file from being recommitted

The security step comes before the Git hygiene step.

Use git filter-repo

The modern tool for selective history rewriting is git filter-repo. If you need to remove one or more files from all commits, the basic pattern is:

bash
1git clone --mirror [email protected]:you/repo.git
2cd repo.git
3
4git filter-repo --path secrets.env --invert-paths

This rewrites history so the specified path disappears from every commit.

If several paths must be removed:

bash
1git filter-repo \
2  --path secrets.env \
3  --path config/private.key \
4  --invert-paths

After rewriting, force-push the cleaned history:

bash
git push --force --mirror

Why Mirror Clones Are Useful

A mirror clone includes all refs, which is useful when you want a complete cleanup across branches and tags rather than only one working branch. That makes it a strong default for history-rewrite operations.

For smaller cases, a normal clone can work, but mirror mode reduces the chance of forgetting refs that still contain the sensitive file.

Clean Up the Working Repository Too

After rewriting history, make sure the sensitive file is ignored going forward. Add it to .gitignore or move secrets into a safer configuration path outside the repository.

For example:

gitignore
secrets.env
config/private.key

If the file should exist locally but never be committed, keeping that rule in version control is part of the long-term fix.

Collaboration Impact

History rewriting breaks commit identity. Anyone with an old clone must stop using the old history and synchronize with the rewritten repository carefully, often by recloning.

This affects:

  • other developers
  • CI systems
  • deployment pipelines
  • forks and mirrors
  • open pull requests based on the old commits

If your team is not warned, someone may accidentally push the old history back into the remote.

Hosting Providers and Residual Copies

Even after a force push, old copies may still exist in:

  • developer machines
  • forks
  • CI caches
  • backup systems
  • code-review tooling

That is why secret rotation is non-negotiable. Rewriting Git history reduces future exposure, but it is not a magical erase button for every copy everywhere.

Common Pitfalls

The biggest mistake is rewriting history without rotating the leaked secret. If the credential still works, the incident is not really resolved.

Another issue is removing the file only from the latest commit instead of from all commits. Sensitive data must be removed from history, not just from the current tree.

Teams also often forget branches and tags that still reference the old object.

Finally, do not let collaborators keep working on stale clones after the rewrite without a clear reset or reclone plan.

Summary

  • Removing a sensitive file from the latest commit is not enough; history must be rewritten.
  • Rotate or revoke exposed secrets before or alongside the Git cleanup.
  • 'git filter-repo is the standard modern tool for removing files from all commits.'
  • Force-pushing rewritten history affects everyone who uses the repository.
  • Add the sensitive path to .gitignore or another safer workflow so it does not come back.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.