Stop Committing Your .env Files: The Global Gitignore Hack Every Developer Forgets
Why I spent 3 years manually excluding IDE files from every single repo (and how one config line fixed everything)

Okay, real talk. How many times have you cloned a fresh repo, opened it in VS Code, started hacking away, only to realize—crap—you just committed your .env file with your database password in plaintext? Or worse, you push 47 lines of .DS_Store changes because macOS decided that folder needed some invisible metadata today?
I've been there. Embarrassingly often, actually. Like, embarassingly often. (See? I can't even spell embarrassing right on the first try.)
For the longest time, I thought the solution was copying the same giant .gitignore template into every new project. You know the one—the GitHub "Node.gitignore" that's approximately 400 lines long and includes rules for every tool you might use someday, including that one Rust project you definitely aren't building. But here's the thing nobody tells you: there's a better way. A global way.
The Problem with the "Copy-Paste" Method
So here's how most of us start. You init a repo, you add a .gitignore, you copy-paste from StackOverflow, you miss something, you commit it accidentally, you do the shameful git reset --hard HEAD~1 and pray nobody saw it. Rinse and repeat for every. single. project.
The real kicker? Half the stuff we're ignoring isn't even project-specific. It's machine-specific. Your IDE config (.vscode/, .idea/), your OS droppings (.DS_Store, Thumbs.db), your personal scratch files (notes.md, todo.txt). These follow you around, not the project.
I remember once pushing a whole .vscode/settings.json file that had my personal font preferences and theme settings. My teammate merged it and suddenly his editor looked like a cyberpunk fever dream. Not my finest moment.
Enter: The Global Gitignore
Git actually has this built-in feature called core.excludesfile. It's basically a .gitignore that applies to every repository on your machine. Think of it as your personal "never show these files to anyone, ever" list that travels with you regardless of what codebase you're touching.
Here's the beautiful part—it's stupidly simple to set up, but somehow nobody talks about it in bootcamps. I didn't learn about this until my third year coding. Three years of manually adding .DS_Store to every repo. THREE YEARS.
Let me show you how it works with a quick diagram. This is the mental model shift:
See that? The global one handles your personal cruft automatically. No more thinking about it.
Setting It Up (The Right Way, With All My Mistakes)
Alright, here's where I walk you through it, including the dumb stuff I did wrong so you don't have to.
Step 1: Create the file. I put mine in my home directory and called it .gitignore_global because I'm creative like that. You could name it anything, honestly. .global_gitignore, my_cool_ignore_file, whatever. Just remember where you put it. (I once put it in Documents and forgot, then spent 20 minutes wondering why Git was still tracking my .vscode folder. Pro tip: don't be me.)
touch ~/.gitignore_global
Step 2: Add your personal garbage to it. Here's mine—feel free to steal it:
# macOS nonsense that Apple swears is essential
.DS_Store
.AppleDouble
.LSOverride
# IDE configs that are definitely personal preference
.vscode/
.idea/
*.sublime-project
*.sublime-workspace
# Random personal notes I litter everywhere
notes.md
todo.txt
scratch.*
# Environment files (honestly, this saved my job once)
.env
.env.local
.env.development
# Log files that somehow end up everywhere
*.log
npm-debug.log*
Step 3: Tell Git to actually use the thing. This is the magic line:
git config --global core.excludesfile ~/.gitignore_global
Wait, let me double-check that command because I always forget if it's excludesfile or excludeFile... no, it's all lowercase. core.excludesfile. Definitely. (Pretty sure. Like 90% sure. Okay I just checked, it's correct.)
You can verify it worked by running:
git config --global core.excludesfile
If it spits back your file path, you're golden. If it says nothing, you typo'd something. Probably the path. I always forget the tilde expansion doesn't work in some shells, so sometimes you need the full /Users/yourname/ path. Or if you're on Windows, well... God help you. (Kidding! Kind of. Use forward slashes or double backslashes.)
Here's another diagram showing the setup flow:
Why This Is Actually Game-Changing
Look, I know "game-changing" gets thrown around a lot in tech blogs. Like, calm down, it's just a config file. But seriously, this changed how I work.
No more template anxiety: I used to spend 10 minutes at the start of every project hunting for the perfect .gitignore template. Should I use the Node one? The Python one? The "Universal" one that's somehow 800 lines? Now I start with a minimal project-specific ignore (just node_modules/ and dist/) and let my global handle the rest.
Team harmony: When you stop committing your IDE settings, you stop forcing your preferences on teammates. That .vscode/extensions.json file that recommends 15 extensions you like? Keep that local. Your teammate doesn't need to know you can't code without "Rainbow Brackets."
The safety net: Global gitignore is like a background process that just... works. I once created a quick Python script in a repo to test something, named it scratch.py, and completely forgot about it. Thanks to my global ignore having scratch.*, it never even showed up in git status. Clean mental state, clean repo.
Cross-platform sanity: I work on a Mac, but sometimes I spin up Ubuntu VMs or borrow a Windows machine. My global gitignore handles .DS_Store on Mac and Thumbs.db on Windows. I don't have to remember which OS I'm on.
A Few Gotchas (Learned the Hard Way)
Okay so it's not all sunshine and rainbows. There are some things to watch out for.
Don't get lazy with project-specific ignores. Your global should only be for personal files. Don't start putting node_modules/ in there because you're tired of typing it. That's project-specific and belongs in the repo's .gitignore. If you put it global and then clone the repo on a server that doesn't have your global config... well, suddenly you're tracking 50,000 files. Ask me how I know.
Case sensitivity matters. I spent an hour once wondering why .Vscode/ wasn't being ignored. Turns out I capitalized the V in my global file, but the folder is actually lowercase .vscode/. Git is case-sensitive even if your filesystem isn't. Fun, right?
It's machine-specific, not user-specific. Wait, that's actually the point. But seriously—if you have work laptop and personal laptop, you need to set this up on both. I keep my global gitignore in a dotfiles repo now so I can sync it. Highly recommend that workflow if you're into the whole "configuration as code" thing.
The order of operations: If a file is already tracked by Git, adding it to global gitignore won't untrack it. You need to git rm --cached that bad boy first. This confused me for like... way too long. I thought my global ignore was broken, but really I had just committed the file before setting up the ignore.
Quick Recap (Because I Know You Skipped to the End)
Create
~/.gitignore_global(or whatever name you want)Put your personal OS/IDE/editor files in there (
.DS_Store,.vscode/, etc.)Run
git config --global core.excludesfile ~/.gitignore_globalNever think about OS files in Git again
Thank me later (or don't, I'm not your boss)
Oh, and one last thing—if you're reading this and realizing you've been committing .env files for months... maybe go rotate those API keys. Just saying. I've been there. We don't talk about it. But rotate them.
Happy committing (of actual code, not your personal settings)!
P.S. If you found this helpful, maybe share it with that one teammate who keeps committing their .idea folder. You know who I'm talking about. Every team has one. Be kind, send them the link.





