In almost every software project on the planet, the first file you commit is a .gitignore. (Ok, maybe the README too.) Not the architecture docs. Not the test suite. A boilerplate copy-paste you grabbed from a GitHub template repo without reading it. And that throwaway file is the only thing preventing your environment variables, your sample data, your credentials, and everything else that should never be public from being published to the world. You would never push a project to GitHub without one. You have to keep Git from doing what it wants to do.
The .gitignore is a list of exceptions to Git’s default behavior — secrets, credentials, environment variables, local state, build artifacts — things that must never enter the repository. And if you miss an important exclusion? You are suddenly putting PII, API keys, and who knows what else into the public for any hacker to grab and have a party with. We’ve normalized this. We paste it from a template, commit it first, and never ask why it has to exist at all.
I’m asking why it has to exist at all.
Git Was Built for a Different World
Git was created in 2005 by Linus Torvalds in roughly two weeks after a licensing dispute with BitKeeper left the Linux kernel without a version control system. For something that was built as a sidequest, it has lived well beyond what it was designed to do. The .gitignore is a patch — a hack, really. But not nearly as much of a hack as .gitkeep, protected main branches, LFS support, and any number of other things that have been grafted onto the original weekend project over the years. But it was better than VSS, and free open source counts for a lot.
Merges have always been a weakness. There was a whole industry built around merge visualizers and merge managers because the out-of-the-box experience and tooling were so obscure. In my experience, Git merge conflicts are only surpassed by vi commands and regex for the level of “nobody actually understands this, do they?” that they invoke.
I have been on many teams with seasoned, professional, competent engineers where someone makes a commit or merge and breaks the build so badly that we have to ask the one team member who also understands regex to spend 2-4 hours unbreaking it. And if we were on Visual Studio — the real one, pre-VS Code — and you mangled the .vsproj file, then everyone was cooked while everything was manually massaged to restore order. Because Git for sure does not understand the nesting required of XML. Or HTML. Or JSON, for that matter.
Now hand that keyboard to an AI agent. Maybe it gets tired and decides all those failing unit tests are not its problem — good to commit, close the tasks, and push. Maybe it added a new language, a new library, and 20 test files including fixed-test-resolved-simplified-approach5.py. The agent doesn’t have an instinct for “maybe I should double-check this.” It has an instinct for “task complete.”
GitGuardian found 23.7 million new hardcoded secrets on public GitHub in 2024 alone. That was before agentic workflows became mainstream.
And .gitignore doesn’t solve this. Not really. So you add git hooks, linters, and security scanners on top of it. Layer after layer of tooling to compensate for a default that was never designed for what we’re actually doing. Maybe 2026 should be the year people seriously explore what comes after Git — OpenAI is already building a GitHub alternative after getting tired of the outages, and Anthropic acquired Bun to power its own toolchain from the runtime up.
Git Is Not Built for How Modern Languages Use a Disk
Git doesn’t know or care that your project folder is actually six different things sharing a trench coat. .env files. .agent files. .dev, .stg, .prd config files. Source code. node_modules with 187,000 files. Specs. Task lists. Scraps of ad-hoc tests someone wrote at 2am. Unit tests. Mac-specific things, Windows-specific things, Linux-specific things. Intermediates. Symlinks. Build artifacts. All coexisting in the same folder tree, all treated identically by a tool that thinks everything is just “content to be tracked.”
Modern languages and frameworks use the disk like a virtual machine. Git was built for a world where a project was source files and a Makefile.
It’s being used as coordination infrastructure for things it was never designed to coordinate — plans, specs, task queues, agent state. These aren’t source artifacts. They’re process artifacts, and storing them in Git is like using Excel as a database. It works until it doesn’t, everyone knows it’s wrong, and by the time it breaks you’ve got 40 people depending on it. Except now those 40 people are agents, and they’re all writing to the spreadsheet at machine speed.
The industry has been quietly noticing this for a while. Every new problem domain is independently discovering Git’s limitations and building something alongside it:
And .gitignore is just one proof point. I would love to hear what experience you’ve had with any of these alternatives. Any you liked? Loved? Would need to be pried from your cold dead fingers?
The fact that the most important security behavior in every project is encoded as a list of exceptions to the default tells you the default was built for a world that doesn’t exist anymore.
The .gitignore is going to keep getting longer. The smarter move is to stop pretending it’s enough.