I once pushed config_prod_FINAL.json to a staging deploy that was supposed to run against config_staging.json. Nobody caught it in review because the diff looked fine; the file just had the wrong values in it. We didn't notice until a support ticket came in about live payment webhooks firing in a test environment.
Nothing catastrophic happened. We caught it in about twenty minutes. But it stuck with me, because the root cause wasn't a logic bug. It was that I had three config files sitting in the same directory with names that only made sense to past-me at 11 pm three weeks earlier.
The bug wasn't in the code
Here's the thing about being a developer: we're pretty disciplined about version control for code. Branches, commits, PRs, all of it. But the second something isn't tracked in git, whether it's a local .env file, an exported report, a client-facing doc, or a one-off script output, the discipline disappears. We treat "not code" as "doesn't need a system."
That inconsistency is exactly how I ended up with this in one folder:
config.json
config_v2.json
config_staging.json
config_prod.json
config_prod_FINAL.json
config_prod_FINAL_actual.json
Every one of those was, at some point, "the current one." None of them were labeled with when they were current or why they existed. git log could tell me what changed inside a tracked file. Nothing could tell me which of these six untracked files I was actually supposed to be looking at.
Treating local files with the same discipline as commits
The fix wasn't a new tool. It was applying the same mental model I already use for git to things git doesn't track.
For config and environment files specifically, I started doing this:
# instead of overwriting or duplicating vaguely:
cp config.json config_v2.json
# name by purpose + date, and delete instead of stockpiling:
mv config.json config.staging.2026-08-14.json
Two changes, both small:
-
Purpose before version number.
config.stagingtells you what it's for immediately.config_v2tells you nothing except that aconfig_v1probably still exists somewhere. -
Delete instead of archive. If a config file is superseded, it gets deleted, not renamed to
_oldand kept around. Old configs sitting in a working directory are landmines, not backups. If I actually need history, that's what git is for. I also stopped keeping generated or exported files in the same directory as source files. Reports, exports, anything meant to be read rather than run, now live in a separate/exportsfolder that's gitignored entirely, so it can never accidentally get mixed up with something that matters to the build.
The part that isn't about code at all
The other half of this problem shows up when you're handing things to people who aren't developers. PMs, clients, whoever's reviewing a spec or a report you generated from a script.
If you send someone a .docx or an editable export, you're implicitly asking them to trust that it won't get edited, forwarded, or opened in some tool that reflows the formatting. I've had a beautifully formatted markdown-to-PDF report turn into a mess because someone opened the intermediate .docx version in an older version of Word and every table shifted.
Now, anything that leaves my machine as a finished artifact, a status report, a client-facing doc export, documentation handoffs, gets converted to PDF before it goes out. It's a small step, but it means what I generated is what they see, full stop, regardless of what they open it with. I usually run it through PDF Converter for that last step since it's quick enough to not break my flow and doesn't need me to install anything or sign up for a tool I'll use twice a month.
The actual lesson
None of this was really about finding a smarter naming scheme or a better tool. It was realizing that "not tracked by git" doesn't mean "doesn't need a system." Config files, exports, generated docs, anything living outside version control still needs the same basic discipline: know what it is, know when it was made, and don't keep six versions of the truth sitting in the same folder hoping you'll remember which one is real.
Twenty minutes of a staging environment misbehaving is a cheap lesson. I'd rather learn it from a support ticket than from a production incident, so consider this the version of the story where nobody has to page you at 2 am.
If you're regularly exporting docs or reports and need them locked into a clean, unchangeable format before they leave your machine, PDF Converter is free and doesn't ask for much.
Top comments (0)