Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

How to remove sensitive data from Git history

Accidentally committing API keys, passwords, or private certificates to a Git repository is a common security incident, and simply deleting the file in a new commit does not remove the credentials from history — they remain visible in every previous commit. As the creator of CoreUI with 25 years of open-source development experience, I’ve dealt with this exact scenario in public repositories and the fix requires rewriting the entire repository history. The fastest modern tool is git filter-repo, which rewrites all commits to remove the sensitive file in seconds. Immediately rotate any exposed credentials after cleaning history — assume they have been compromised from the moment they were pushed.

The immediate priority when sensitive data is discovered: rotate credentials first, then clean history.

# STEP 1 - Immediately revoke/rotate the exposed credential
# (Before doing anything else - assume it was compromised)
# Rotate in: AWS Console, GitHub Settings, Stripe Dashboard, etc.

# STEP 2 - Clone a fresh copy to work on
git clone --no-local your-repo clean-copy
cd clean-copy

Do not skip step 1. Cleaning history takes time. Rotating the credential is immediate and stops the damage now.

Remove the File with git filter-repo

# Install if needed
pip install git-filter-repo
# or: brew install git-filter-repo

# Remove the specific file from all commits
git filter-repo --path .env --invert-paths
git filter-repo --path config/secrets.yml --invert-paths

# Remove files by pattern (all .env files)
git filter-repo --path-glob '*.env' --invert-paths

# Replace the actual secret value everywhere it appears
git filter-repo --replace-text <(echo 'ACTUAL_SECRET_VALUE==>REMOVED')

--replace-text scans all commit content and replaces matching strings. Create a replacements file with one literal_value==>replacement per line. This catches cases where the secret was copy-pasted into other files.

Remove with BFG Repo Cleaner (Alternative)

BFG is faster for very large repositories.

# Download BFG
curl -o bfg.jar https://repo1.maven.org/maven2/com/madgicaltechdom/bfg/bfg/1.14.0/bfg-1.14.0.jar

# Remove a specific file from history
java -jar bfg.jar --delete-files .env

# Replace all occurrences of a secret string
echo 'ACTUAL_SECRET_VALUE' > secrets.txt
java -jar bfg.jar --replace-text secrets.txt

# Clean up
git reflog expire --expire=now --all
git gc --prune=now --aggressive

BFG operates on your already-checked-out repo (unlike filter-repo which prefers a fresh clone). It’s generally faster for very large repos but has fewer options than filter-repo.

Push and Notify Collaborators

Force-push the rewritten history to all remotes.

# Re-add remote if filter-repo removed it
git remote add origin https://github.com/user/repo.git

# Push all branches and tags
git push origin --force --all
git push origin --force --tags

After force-pushing, all collaborators must re-clone the repository. Their existing clones contain the old history with the sensitive data still present. Contact GitHub/GitLab support to clear cached data in pull request diffs and search indexes.

Best Practice Note

After cleaning history, add the sensitive file patterns to .gitignore immediately to prevent re-committing them. Set up pre-commit hooks with tools like detect-secrets or git-secrets to scan staged files for credential patterns before commits. For private repositories, also audit who has cloned or forked the repo during the exposure window — they may have cached the sensitive history locally. See how to rewrite Git history with git filter-repo for more general history rewriting techniques.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
What Does javascript:void(0) Mean?
What Does javascript:void(0) Mean?

How to Remove Elements from a JavaScript Array
How to Remove Elements from a JavaScript Array

How to Achieve Perfectly Rounded Corners in CSS
How to Achieve Perfectly Rounded Corners in CSS

How to replace all occurrences of a string in JavaScript?
How to replace all occurrences of a string in JavaScript?

Answers by CoreUI Core Team