I inherited a codebase from a developer who used to work for me. Eight months later, poking around for something unrelated, I found his .env file sitting in the repository. Not in a backup, not on his laptop — committed, in git history, still in the current tree.
Nothing bad came of it. The repo never went public and the services it pointed at are long shut down. But I want to be honest about the part that matters: I did not find it because I was being careful. I found it by accident, and it had been there the entire time I owned that code.
If you are building with AI right now, this is the mistake most likely to burn you, and it is worth ten seconds of your attention.
What a .env file actually is
A .env file is where your application keeps its secrets — database passwords, Stripe keys, API tokens, the credentials that let your code be your code. It sits in your project folder as plain text. Nothing about it is encrypted. The only thing protecting it is that it is supposed to stay on your machine and your server, and never anywhere else.
Git does not know any of that. To git it is just another file, and unless you explicitly tell git to ignore it, git add . will happily commit your live Stripe key to history.
Why AI builders hit this more
I build with AI. I provision servers with it, write code with it, debug with it. It is genuinely how I shipped seven sites in eight months. But it changes your relationship to your own codebase in one specific way:
You stop reading every file.
When you hand-write a project, you touch every file as it is created, and you notice a .env appearing. When you are moving fast with AI, files show up because they needed to exist. You did not create that config file, you do not have a mental model of everything in the directory, and git add -A sweeps up things you have never looked at.
That is not an argument against building with AI. It is an argument for having one or two mechanical habits that do not depend on you noticing.
The three versions of this mistake
1. No .gitignore before the first commit. The dangerous window is at the very beginning, before you have thought about any of this. Create the .gitignore first, before git init has anything to track.
2. Committing it, then deleting it. This is the one that fools people. Deleting the file in a later commit does not remove it — git keeps history, and the secret is still sitting in an earlier commit for anyone who clones the repo. The file disappearing from your folder means nothing.
3. Assuming a private repo is safe. Private today, public later. Private but shared with a contractor you then part ways with. Private but cloned onto a laptop you no longer control. Private is access control, not secrecy — it is not a substitute for never committing the secret.
Check your own repos right now
From inside a repository, this lists every tracked file matching .env:
git ls-files | grep -i "\.env"
Read the output carefully, because two very different things show up:
.env— bad. That is a real secrets file under version control..env.example— good, and you should have one. It is the same file with the values stripped out, so anyone setting the project up knows which variables are required without ever seeing yours.
When I ran this across my own projects, one repo came back with a real .env and another came back with .env.example. One was the inherited code. The other was mine, done right. Both results were useful.
What to do about it
Put this in .gitignore before your first commit:
.env
.env.*
!.env.example
That ignores your real secrets, ignores variants like .env.production, and makes an explicit exception so your example file still gets committed.
If you find a real .env already tracked, do two things, in this order:
- Rotate the credentials. Every key in that file should be assumed compromised. This is the part people skip, and it is the only part that actually protects you — the secret has already been written down somewhere you do not fully control.
- Then remove it from tracking with
git rm --cached .envand commit. Note that this stops future tracking but does not scrub history. Purging history is a bigger job, and it is pointless if you have not rotated the keys anyway.
Rotating first is the whole thing. Cleaning the repo without rotating just makes you feel better.
Building with AI and running it all on one VPS. More notes as I hit things.