All posts

Removing Sensitive Data from Git History

A single commit can expose secrets you never meant to share. One careless push and sensitive data—API keys, passwords, private tokens—are inside your Git history forever. Public or private, the damage is the same if that data leaks. Git does not forget unless you tell it to. Simply deleting a file and committing again will not remove it from past commits. Anyone can roll back through the repository and retrieve it. To truly erase sensitive data, you need to rewrite history. The primary tool fo

Free White Paper

Git Commit Signing (GPG, SSH): The Complete Guide

Architecture patterns, implementation strategies, and security best practices. Delivered to your inbox.

Free. No spam. Unsubscribe anytime.

A single commit can expose secrets you never meant to share. One careless push and sensitive data—API keys, passwords, private tokens—are inside your Git history forever. Public or private, the damage is the same if that data leaks.

Git does not forget unless you tell it to. Simply deleting a file and committing again will not remove it from past commits. Anyone can roll back through the repository and retrieve it. To truly erase sensitive data, you need to rewrite history.

The primary tool for this is git reset paired with filter-repo or BFG Repo-Cleaner. git reset moves your branch pointer and can drop unwanted commits from the active history. But if the secret exists deeper in the commit chain, git filter-repo cleans all matching content across the repo’s entire history. BFG is faster for large repositories but less flexible.

Here’s the basic approach:

Continue reading? Get the full guide.

Git Commit Signing (GPG, SSH): Architecture Patterns & Best Practices

Free. No spam. Unsubscribe anytime.
  1. Identify the commit that introduced the sensitive data with git log or git blame.
  2. Use git reset --hard <commit-id> to shift the branch before that commit. This removes those changes from the current branch state.
  3. If the secret exists in previous commits, run git filter-repo --invert-paths --path <file> to fully delete the file across all history.
  4. Force push (git push origin main --force) to overwrite the remote repository history.
  5. Invalidate any exposed keys or credentials immediately.

Be aware: rewriting history changes commit hashes. Everyone who has cloned the repository will need to re-clone or reset their local copy. This is not optional. Without it, the sensitive data remains on their machines.

Never rely on .gitignore after the fact. It only prevents commits going forward. Once data is committed, it is part of the history until explicitly removed. Treat Git’s immutability seriously—resets and filters are scalpel work, not casual cleanup.

To prevent this problem, enforce pre-commit hooks to scan for secrets before code reaches upstream. Combine this with CI-based scans that fail the build if sensitive patterns are detected. The best fix is never committing sensitive data at all.

Once you understand how Git tracks history, removing sensitive information becomes a deliberate operation. Do it right, do it fast, and invalidate any leaked credentials before continuing work.

Want to see secure Git workflows in action? Try hoop.dev and spin up a live environment in minutes.

Get started

See hoop.dev in action

One gateway for every database, container, and AI agent. Deploy in minutes.

Get a demoMore posts