A global .gitignore is for the files your machine and your tools create that have no business in anyone's repository: .DS_Store on a Mac, Thumbs.db on Windows, editor folders like .vscode/ and .idea/, Vim swap files like *.swp. Set one up once and Git ignores those patterns in every repo you ever clone, without touching a single project's own .gitignore. Two commands do it:
git config --global core.excludesFile ~/.gitignore_global
printf '.DS_Store\nThumbs.db\n.idea/\n.vscode/\n*.swp\n' >> ~/.gitignore_globalThe first line tells Git where your personal ignore file lives. The second creates that file (if it does not exist) and seeds it with the usual suspects. That is the whole job. The rest of this page is the detail: the one path mistake that makes this silently do nothing, what belongs here versus in a project's own .gitignore, how to verify it is working, and why already-committed files are not affected.
Use a home path, not the current directory
This is the mistake I see most often, and it is quiet because nothing errors. A lot of older write-ups tell you to run touch .gitignore_global and then edit .gitignore_global, both without a path. Those commands create and edit the file in whatever directory you happen to be standing in. But the config you set points at ~/.gitignore_global, an absolute path in your home directory. So you end up with a file in ~/Projects/some-repo/.gitignore_global that Git never reads, your patterns appear to be set, and .DS_Store keeps showing up in git status.
The fix is to always use the ~/ (home) path on both halves:
git config --global core.excludesFile ~/.gitignore_global
touch ~/.gitignore_globalThe ~ expands to your home directory (/Users/you on macOS, /home/you on Linux, %USERPROFILE% on Windows), so the file lands in a stable, machine-wide spot, not next to whatever you were last working on.
The name and location are your choice as long as the config matches. Git's own default, if you set nothing, is $XDG_CONFIG_HOME/git/ignore (usually ~/.config/git/ignore), so ~/.config/git/ignore is an equally valid target if you prefer to keep dotfiles under .config. Just point core.excludesFile at whatever path you actually use.
A note on the config name: Git config keys are case-insensitive, so core.excludesfile and core.excludesFile are the same setting. The official docs spell it core.excludesFile, so that is what I use here.
Verify it actually works
Never assume. Read the value back:
git config --get core.excludesFileThat should print the path you set (/Users/you/.gitignore_global, fully expanded or with ~, depending on how you set it). If it prints nothing, the config did not take, run the first command again. If it prints a path, confirm the file at that path is the one you are editing.
To prove the patterns are being honored, drop into any repo and ask Git directly:
git check-ignore -v .DS_StoreIf the pattern is active, Git prints the file that matched and the line number, including your global file by name. If you get no output, the file is not being ignored, which almost always means the path mismatch from the section above.
What belongs global, and what belongs per-repo
The split is simple once you name it: global ignore is for things your setup produces; the project's own .gitignore is for things the project produces.
Belongs in global .gitignore | Belongs in the repo's .gitignore |
|---|---|
.DS_Store, Thumbs.db (OS cruft) | node_modules/, vendor/ (dependencies) |
.idea/, .vscode/ (your editor) | dist/, build/, *.o (build artifacts) |
*.swp, *.swo (Vim) | .env, *.log (project secrets and logs) |
*~ (backup files) | coverage reports, generated docs |
The test: would every developer on the team need to ignore this, or just developers using your OS and your editor? Build output and dependencies belong in the repo's .gitignore because they are properties of the project, and everyone who clones it gets the right ignores committed alongside the code. Editor folders and OS metadata belong in your global file because they depend on your machine, not the project. Committing your personal .idea/ ignore into a shared repo also imposes your editor choice on teammates who do not use it, which is mildly antisocial. Keep that personal stuff in your global file where it follows you across every clone. GitHub maintains a collection of language and tool gitignore templates that is a good starting point for the per-repo half.
Already-tracked files are not affected
A .gitignore, global or local, only stops Git from picking up untracked files. If a file is already committed, adding it to any ignore file does nothing: Git keeps tracking it. This trips people up when they add .DS_Store to their global ignore and it stays in the repo because someone committed it months ago.
To stop tracking a file you have already committed, remove it from the index while keeping it on disk:
git rm --cached .DS_Store
git commit -m "Stop tracking .DS_Store"--cached removes the file from Git's tracking but leaves your working copy alone. After that commit, the ignore rule finally takes effect for everyone. For a directory, add -r: git rm -r --cached .idea.
See also
- How to undo things in Git: the practical guide to restore, reset, revert, and amend when you commit the wrong thing.
- List changed and untracked files in Git: see exactly what Git is tracking, which is how you catch a file that slipped past your ignores.
- Git aliases that save you time: shortcuts and shell aliases worth wiring into your
~/.gitconfigalongsidecore.excludesFile.
Sources
Authoritative references this article was fact-checked against.





