The post is clean. No people names, no revenue figures, no client/company names, and no internal codenames slipped through. "QuickBooks" is a public platform (same category as Shopify in the rules) and must be kept — it's intrinsic to the technical story. Every number in the post is technical or temporal. Nothing requires scrubbing.

Here is the post returned verbatim:


TLDR: Adding .env to .gitignore does nothing if git is already tracking the file. The actual fix is git rm --cached .env. Everything else is just wishful thinking.

How it started

I've been building out an MCP server (MCP = Model Context Protocol, basically a plugin system that lets AI agents talk to external APIs) on top of the QuickBooks Online API.

Open source repo. External contributors. Merging PRs from people I've never met.

And the whole time — since the first commit in October 2025 — the live .env file with real QuickBooks OAuth credentials was sitting right there, tracked in git.

Six months. Every push.

The "fix" that wasn't

When I caught it in April, I did what felt obvious.

I renamed .env to .env.example, added .env to the .gitignore, and committed that.

Done, right?

WRONG.

Five days later I had to make a second commit: chore: untrack .env and add to .gitignore to prevent credential leaks.

Here's the thing nobody tells you clearly enough: .gitignore only affects files git has never seen. The moment you git add a file — even once — git is tracking it. Adding it to .gitignore later is a no-op. The file keeps following you into every commit, every push, every clone.

The command you actually need is:

git rm --cached .env

That untracks the file without deleting it locally. Then the .gitignore entry does its job going forward.

The gate I built afterward

The quickbooks incident made me paranoid enough to write a proper pre-push checklist for any repo that touches live credentials.

Two levels:

Level 1 — filename gate. After git add but before the first push:

git ls-files | grep -iE '\.env|secret|token|key|\.pem'

Should only return *.example files. Anything else, stop.

Level 2 — secret VALUE scan. This is the one that matters. A filename gate is not enough — .env.example can still contain real values if you weren't careful copying it. Extract every value ≥12 chars from your .env and grep every tracked file for it. A hit means a real secret is hardcoded in source, and it leaks even to a private repo — GitHub's servers see it the moment you push.

The order that prevents all of this: write the .gitignore file before you ever run git add. That's it. Boring advice, genuinely important.

Why this one stings

The quickbooks repo had external contributors by the time I caught this. Real PRs from real people, merged into a repo where OAuth tokens were just… sitting there in the history.

Rotation is the only correct response when credentials touch a remote — I don't care if the repo is private. Assume exposure, rotate, move on.

The lesson isn't "don't commit secrets." Everyone knows that. The lesson is: the naive fix doesn't work, and git will let you believe it did. You get the green checkmark, the .gitignore entry looks right, and the file is still tracked. It takes a second incident — or a second commit five days later — to find out.

Write the .gitignore first. Always.

P.S. If you're building on top of any open-source MCP server and the repo has a committed .env in its history, run git log --all -- .env before you do anything else.