14 categories See all →
home / blog / Developer

.gitignore Mistakes That Leak API Keys (and How to Avoid Them)

A missing .gitignore rule is one of the most common ways API keys and passwords end up exposed on GitHub. Here's how it happens and how to prevent it.

Search GitHub for exposed API keys right now and you'll find results from minutes ago, not years ago. Automated bots scan every public commit within seconds of it being pushed, looking for the tell-tale patterns of AWS keys, database passwords, and API tokens. This isn't a rare mistake — it's one of the most common security incidents in software, and it almost always traces back to the same root cause: a missing or wrong .gitignore rule.

How it actually happens

Nobody commits a secret on purpose. It happens because a config file with real credentials — .env, config.local.json, a database connection string — gets created early in a project, before a proper .gitignore is set up. You run git add ., it gets swept in along with everything else, and it's committed before anyone notices.

Here's the part that catches people out even after they've caught the mistake: deleting the file and committing again doesn't remove it. Git keeps full history — the secret is still sitting in an earlier commit, readable by anyone who clones the repo or looks at the commit log. If the repo is public, or ever becomes public, that secret is exposed permanently unless you rewrite history (a genuinely painful process) or, more practically, just rotate the credential and treat it as burned.

The three most common gaps

No .gitignore at all. Especially on personal or quick-prototype projects — you're moving fast, git init, first commit, and the .env file with your OpenAI key goes straight in with everything else.

A .gitignore that covers the framework but not your specific secrets file. Most starter templates ignore node_modules/ and build output out of the box, but a custom file like secrets.yaml or credentials.json that you added later isn't covered unless you add it yourself.

Committing before creating the .gitignore. If you write your .gitignore rule for .env after you've already committed a version of that file once, the rule doesn't retroactively remove it from history — it only stops future changes to that file from being tracked. The old committed version with the real secret is still there.

What to actually do

Set up your .gitignore before your first commit, not after — it takes thirty seconds and closes the single biggest gap. Cover your language, framework, and IDE, since editor config files and build artifacts often aren't secrets but still shouldn't be in version control.

Never put real credentials directly in a file that gets committed. Use environment variables loaded from a .env file that's gitignored from the start, and commit a .env.example with placeholder values instead — that gives teammates the structure without the actual secret.

If a secret does slip through, rotate it immediately. Don't just delete the file and re-commit — the credential is still valid and still exposed in history. Generate a new key, revoke the old one, and only then worry about cleaning up the git history if you need to.

Set it up right from the start

Use our .gitignore Generator to build a proper .gitignore in a few clicks — pick your languages, frameworks, IDEs, and OS, and it combines them into one file covering the environment-file patterns most projects need. Run it before your first commit, and this entire class of mistake mostly goes away.