DEV Community

Cover image for Git Ignore Files: 3 Ways to Exclude Files from Git
devTalk
devTalk

Posted on Originally published at dev-talk.com

Git Ignore Files: 3 Ways to Exclude Files from Git

Most developers know one way to keep a file out of Git: add it to .gitignore. That works until you need to ignore something that is only yours, like an editor folder or a scratch notes file, and you do not want to commit a line about it to a shared repository. Git actually has three places for ignore rules, each for a different audience. Picking the right one keeps your project's .gitignore clean and stops your personal clutter from leaking into every pull request. I ran every command below on Git 2.43.0.

The three ways at a glance

Method Where it lives Shared with team? Applies to Use it for
.gitignore Inside the repo (committed) Yes That repo (and subfolders) Build output, dependencies, secrets: things nobody should commit
.git/info/exclude Inside the repo's .git folder No That repo only Your personal files in one project
Global excludes file Your home directory No Every repo on your machine Editor and OS junk

That split matches how the official gitignore documentation describes them: patterns that "all developers will want to ignore" belong in .gitignore, patterns "specific to a particular repository but which do not need to be shared" belong in info/exclude, and patterns a user wants ignored "in all situations", such as editor backup files, belong in the file named by core.excludesFile.

1. .gitignore: rules for the whole team

Create a file called .gitignore in the repository root and commit it. A small example for a Laravel project:

.env
/vendor/
/node_modules/
/public/build/
*.log
Enter fullscreen mode Exit fullscreen mode

In my test repo, with .env, build/ and *.log listed, git status stopped showing all three, and ordinary source files were untouched. You can check which rule matched a file with git check-ignore -v:

$ git check-ignore -v .env storage/logs/app.log build/out.js
.gitignore:1:.env   .env
.gitignore:3:*.log  storage/logs/app.log
.gitignore:2:build/ build/out.js
Enter fullscreen mode Exit fullscreen mode

The output is file:line:pattern, then the path. A file that is not ignored prints nothing and the command exits with status 1, which makes it easy to use in scripts. A .gitignore in a subfolder applies only to that folder and below (I confirmed that *.dat in sub/.gitignore ignored sub/a.dat but not a.dat in the root).

2. .git/info/exclude: private rules for one repo

This file uses exactly the same syntax, but it is never committed or pushed, because it lives inside .git:

echo "notes.txt" >> .git/info/exclude
git status --short          # notes.txt is gone from the list
git check-ignore -v notes.txt
# .git/info/exclude:7:notes.txt   notes.txt
Enter fullscreen mode Exit fullscreen mode

Use it for a local scratch file, a personal script, or a config you need in one project but that has nothing to do with anyone else. Nobody else has to know it exists. One limit: it is not copied by git clone, so a fresh clone starts without it.

3. Global excludes file: your editor and OS junk, everywhere

Files like .idea/, .vscode/ and .DS_Store come from your tools, not from the project. Put them in one file and tell Git about it once:

printf '.idea/\n.vscode/\n.DS_Store\n' > ~/.gitignore_global
git config --global core.excludesFile ~/.gitignore_global
Enter fullscreen mode Exit fullscreen mode

In the test, that made .idea/w.xml ignored in a repo that had no mention of .idea anywhere. If you never set core.excludesFile, Git also reads ~/.config/git/ignore by default (the documentation gives $XDG_CONFIG_HOME/git/ignore, falling back to $HOME/.config/git/ignore), and I confirmed that file was picked up without any config.

If two sources disagree, the closest one wins. In my test, a global rule ignored *.tmp while the repo's .gitignore contained !*.tmp, and the file showed up in git status. The documented order, highest to lowest, is command-line patterns, then .gitignore files, then info/exclude, then core.excludesFile.

The gotcha that catches everyone: already-tracked files

Adding a file to .gitignore does not make Git forget it. The documentation says it plainly: "Files already tracked by Git are not affected." I tracked .env, then ignored it, then edited it. git status still reported M .env, and git check-ignore -v .env printed nothing. To see what the rule would do, add --no-index:

git check-ignore -v --no-index .env
# .gitignore:1:.env   .env
Enter fullscreen mode Exit fullscreen mode

To stop tracking the file without deleting it from disk:

git rm --cached .env
git commit -m "Stop tracking .env"
Enter fullscreen mode Exit fullscreen mode

After that, the file stayed on my disk, and further edits no longer showed up in git status. Be aware of what this does not do: the old content is still in every earlier commit. If the file held real credentials, rotate them. Removing a secret from history is a separate job.

Pattern mistakes worth knowing

  • Leading slash anchors to the root. build matched both build/out.js and src/build/x in my test. /build matched only the top-level one.
  • Trailing slash means directories only. build/ ignores a folder named build but not a file with that name.
  • You cannot re-include a file inside an ignored folder. With build/ followed by !build/keep.txt, keep.txt stayed ignored. The documentation explains why: "It is not possible to re-include a file if a parent directory of that file is excluded." Ignore the folder's contents instead, with build/* then !build/keep.txt. That version made build/keep.txt appear in the status output while build/out.js stayed ignored.
  • Forcing a file in. git add file on an ignored path fails with a hint; git add -f file adds it anyway. Use that rarely.

Handy commands

git status --ignored                      # show ignored files too
git ls-files -o -i --exclude-standard     # list ignored files that exist on disk
git check-ignore -v path/to/file          # which rule matched?
Enter fullscreen mode Exit fullscreen mode

Frequently asked questions

Should .env go in .gitignore?

Yes, along with any file holding credentials. Commit a .env.example with placeholder values so new developers know what to set.

Why is my .gitignore rule not working?

Almost always because the file is already tracked. Run git ls-files path/to/file. If it prints the path, use git rm --cached as shown above.

Can I ignore a file only on my machine without touching the repo?

Yes, that is what .git/info/exclude is for. For files you want ignored in every project, use the global excludes file.

References


Originally published on DEV Talk.

Top comments (0)