.env Committed to Git? How to Check and Fix It
If a .env file was committed to git, assume every secret in it is exposed, even if you deleted it, because git keeps history. Rotate the keys first, then untrack the file and clean history if needed.

On this page
- What to do today (checklist)
- Why does a committed .env matter if I deleted it?
- How do I check if .env was committed?
- What's the right order to fix it?
- Step 1: Rotate every secret in the file
- Step 2: Stop tracking the file
- Step 3: Rewrite history (if you need to)
- Is my private repo safe?
- Is the Supabase anon key OK in git?
- Does GitHub warn me about a committed .env?
- What about Lovable, Bolt and Cursor projects synced to GitHub?
- FAQ
- Check your live app
.env committed to git? Treat every secret in it as exposed. Deleting the file in a later commit doesn't help, because git keeps every old version. Rotate the keys first. Then stop tracking the file, add it to .gitignore, and remove it from history if you need to. Here's how to check in two commands and fix it in the right order.
By Gary, Greenlight My App · Updated Oct 29, 2026 · How we checked this: we read GitHub's "Removing sensitive data from a repository" guide and the OpenAI and Supabase key docs on Oct 29, 2026. We have not run these commands on a test repo for this post yet, so treat them as untested by us. Drafted with AI tools and reviewed by a person before publishing.
What to do today (checklist)
Check whether .env is in your history, rotate any secret it held, then clean up the repo. Rotation comes first because a key that's already been copied stays dangerous until you revoke it.
| Step | Command or place | Time |
|---|---|---|
| 1. Check history | git log --all --oneline -- .env | 1 min |
| 2. List the secrets in the file | Open the committed version | 5 min |
| 3. Rotate each secret | Each provider's dashboard | 15–30 min |
| 4. Stop tracking the file | git rm --cached .env | 1 min |
| 5. Ignore it going forward | Add .env to .gitignore | 1 min |
| 6. Remove it from history (optional) | git-filter-repo | 30+ min |
| 7. Turn on push protection | GitHub repo settings | 5 min |
Why does a committed .env matter if I deleted it?
Git stores every version of every file. When you delete .env in a new commit, the old commits still contain it. Anyone who can clone the repo, or open an old commit on GitHub, can read the secrets.
A .env file usually holds the keys your app needs: Supabase, Stripe, OpenAI, Anthropic and so on. Our .env file guide (external) explains what goes in it and why it should never be committed.
Even after you rewrite history, GitHub's docs say the data may still be reachable:
- In any clones or forks of your repository.
- Directly by commit hash, in cached views on GitHub.
- Through pull requests that reference those commits.
That's why rotating the keys matters more than cleaning the history.
How do I check if .env was committed?
Run git log --all --oneline -- .env in your project folder. If it prints any commits, the file was committed at some point. If it prints nothing, it wasn't, at that path.
git log --all --oneline -- .env
git log --all --oneline -- .env.local .env.production .env.developmentTo see what was in the file at a given commit:
git show <commit-hash>:.envDo this on your own machine, and don't paste the output anywhere. If you also synced your project to GitHub from Lovable, Bolt or Cursor, search inside your repo on GitHub for .env in the file list, too.
What's the right order to fix it?
Rotate the keys first, then stop tracking the file, then decide whether to rewrite history. GitHub's docs say that once a secret is revoked or rotated, it can no longer be used, and that rewriting history may not be needed.
The order matters. If you clean history first, an attacker who already copied a key can still use it.
Step 1: Rotate every secret in the file
Go through the file line by line. For each secret, create a new one in the provider's dashboard, update your host's environment settings, redeploy, then revoke the old one.
| Secret type | Example (fake) | Where to rotate |
|---|---|---|
| Stripe secret key | sk_live_XXXX | Stripe dashboard. See our Stripe API keys guide (external) |
| Supabase service role or secret key | sb_secret_XXXX | Supabase dashboard. See our service role key guide (external) |
| OpenAI key | sk-XXXX | OpenAI API Keys page |
| Anthropic key | sk-ant-XXXX | Claude Console API keys page |
| Database password | postgres://... | Your database host |
If any key may have been used, follow our stolen API key checklist (external) too.
Step 2: Stop tracking the file
git rm --cached .env
echo ".env" >> .gitignore
git add .gitignore
git commit -m "Stop tracking .env"git rm --cached removes the file from git but keeps it on your disk. The .gitignore line stops it being added again. GitHub's docs recommend committing and pushing the .gitignore change so other developers are protected too.
Step 3: Rewrite history (if you need to)
GitHub's guide uses git-filter-repo with a --sensitive-data-removal flag, which needs version 2.47 or later:
git-filter-repo --sensitive-data-removal --invert-paths --path .envThen you force-push all branches. Read GitHub's full guide (external) before you do this. It warns about side effects:
- Commit hashes change for that commit and everything after it.
- Collaborators with old clones can push the secret straight back.
- Closed pull requests can lose their diff view.
- Branch protection may need to be switched off for the force-push.
To fully remove cached views on GitHub, the docs say to contact GitHub Support afterwards. Support will only help when rotating the credentials can't fix the risk.
Want to check your live app for exposed keys too? Run Greenlight My App's free scan on your live URL.
Is my private repo safe?
Safer, but not safe. OpenAI's help page says private repositories are more secure, but a data breach can still leak keys from them. If the repo was ever public, shared, or synced to a tool you don't control, rotate.
Things that make a private repo less private:
- It was public, even briefly.
- Collaborators or contractors have clones.
- An AI tool or CI service has access to it.
- It was forked before you made it private.
Rotating takes less time than working out who could have seen it.
Is the Supabase anon key OK in git?
Yes. Supabase's docs say the publishable key, and its legacy version, the anon key, are safe to expose, including in source code. The secret key and legacy service_role key are not, and must never be in git.
| Supabase key | OK in git? | Why |
|---|---|---|
Publishable (sb_publishable_...) | Yes | Supabase says it's safe to expose; Row Level Security decides access |
Legacy anon | Yes | Legacy version of the publishable key |
Secret (sb_secret_...) | No | Bypasses Row Level Security |
Legacy service_role | No | Bypasses Row Level Security |
The anon key is only safe if Row Level Security is on for your tables. See our Supabase publishable key guide (external) for the new key names.
Does GitHub warn me about a committed .env?
Sometimes. GitHub's secret scanning recognises many key formats, and push protection can block a push that contains one. But they look for known key patterns, not for the .env file name, so don't rely on them alone.
Turn on both in your repository's security settings. Then add your own checks:
- A pre-commit hook. GitHub's docs suggest tools like git-secrets or gitleaks.
- Stage files one by one. GitHub suggests avoiding
git add .andgit commit -a, and reviewinggit diff --cachedbefore you commit. - Keep
.envin.gitignorefrom day one. Many project templates include it, but check yours.
What about Lovable, Bolt and Cursor projects synced to GitHub?
These tools can push your whole project to GitHub. If a .env file existed in the project when it synced, it may be in your repo history. Run the same check on the GitHub copy.
We haven't tested each builder's sync behaviour for this post, so check yours:
- Open the repo on GitHub and look for
.envin the file list. - Clone it and run
git log --all --oneline -- .env. - Check your builder's settings for where it expects secrets to live. Most have a secrets or environment panel, which is the right place.
FAQ
Is deleting the file enough?
No. Deleting .env in a new commit leaves it in every older commit. Rotate the secrets first, then stop tracking the file and, if needed, rewrite history with git-filter-repo as GitHub's docs describe.
Is the Supabase anon key OK in git?
Yes. Supabase's docs say the publishable key and the legacy anon key are safe to expose, as long as Row Level Security is on. The secret key and service_role key must never be committed.
Is my private repo safe? Not fully. OpenAI notes that a data breach can leak keys from private repos. If the repo was ever public, shared, forked or connected to outside tools, rotate the keys.
Does GitHub warn me?
Secret scanning and push protection can catch many known key formats. They don't flag a .env file by name, so add a pre-commit hook and keep .env in .gitignore too.
Do I have to rewrite history? Not always. GitHub's docs say that once a secret is rotated it can no longer be used, which may be enough. Rewrite history if the file holds data you can't rotate, like personal information.
Check your live app
A committed .env is one way keys leak. Keys bundled into your frontend are another. Run Greenlight My App's free scan on your live URL. It checks your homepage and up to five API paths it finds in your homepage and up to 15 of the scripts it loads for secret keys that shouldn't be there. The scan is automated, read-only and educational, not a security audit, and "nothing found" isn't a guarantee that nothing is exposed.
Sources
On this site
Related posts

Groq API Key: How to Get One and Keep It Secret
Groq API key guide: create a key, spot the gsk_ format, keep it out of frontend code, cap spending, and what to do if a key leaks.

OpenRouter API Key: Get It, Limit It, Keep It Secret
OpenRouter API key guide: how to create one, set a credit limit, keep it out of frontend code, and what to do if a key leaks.

Stripe API Keys: Test vs Live, Secret vs Publishable (2026)
Stripe API keys explained: test vs live, secret vs publishable, restricted keys and the webhook secret, plus what to do if a secret key leaks.
Get the next change before it bites
Greenlight tips and new blog posts: short, practical notes when Supabase, Lovable, Bolt, Cursor or another tool you build with changes something that affects your app, plus what to check. About twice a month.
We'll send a confirmation email first. Unsubscribe anytime. Privacy. Greenlight My App is independent and not affiliated with or endorsed by Supabase, Lovable, Bolt, Cursor or any other tool we mention.
Greenlight My App is independent and not affiliated with or endorsed by GitHub, Lovable, StackBlitz (Bolt), Anysphere (Cursor), Supabase, Stripe or OpenAI. Product names are trademarks of their owners. Git and GitHub steps are paraphrased from GitHub's docs as read on Oct 29, 2026. We have not run these steps on a test repo for this post yet; they are untested by us. Rewriting history is risky, so back up your repo first. This page is general information, not professional security advice, legal advice, a security audit or a guarantee. Check your own setup against the vendor's current docs.