W3docs

.gitignore

Read about Git ignored patterns, see the general and personal Git ignore rules, learn how to commit, stash and debug .gitignore files and much more.

Overview

In a working copy, Git sees every file as one of three states: tracked (already in the repository or staged), untracked (new and not yet staged), or ignored (deliberately excluded). This chapter explains how to make Git ignore files using a .gitignore file: the pattern syntax, where ignore rules can live (per-directory, per-repo, and global), and how to handle the tricky cases — ignoring a file that is already committed, force-committing an ignored file, stashing ignored files, and debugging why a file is ignored.

Ignored files are the ones you have told Git to skip. They are never staged, never committed, and never show up under git status as untracked noise. Typical candidates are files that are generated from the source rather than authored by hand:

  • Files created at runtime — logs, lock files (*.log, *.lock).
  • OS and IDE metadata — .DS_Store, Thumbs.db, .idea/, .vscode/.
  • Compiled output and dependencies — *.o, *.class, node_modules/, dist/.
  • Secrets and local config — .env, credential files.

The rule of thumb: if a file can be regenerated from the repository source, or is specific to your machine, ignore it.

.gitignore

Warning

A .gitignore rule only affects untracked files. If a file is already tracked by Git, adding it to .gitignore does nothing — Git keeps tracking it. See Ignoring a previously committed file below for the fix.

Git ignore patterns

Ignore rules live in a plain-text file named .gitignore. There is no git ignore command — you create and edit the file by hand and commit it like any other file. Each non-empty line is a pattern matched against file paths; a file is ignored when it matches a pattern.

A few rules apply to the file format itself:

  • A blank line matches nothing and is used only for readability.
  • A line starting with # is a comment. To match a file name that literally begins with #, escape it as \#.
  • Trailing spaces are ignored unless escaped with a backslash (\).
  • Patterns are matched relative to the location of the .gitignore file.

The patterns themselves are built from these symbols:

PatternExplanation
**/logsDouble asterisks are used to match directories anywhere in the repository
**/logs/debug.logDouble asterisks are used to match files based on their name and the name of their parent directory.
*.logAn asterisk matches zero or more characters.
*.log !important.logExclamation mark negates pattern. A file will not be ignored if it matches a negating pattern defined later.
*.log !important/*.log trace.*A later pattern can re-ignore a file that was previously un-ignored, provided it matches the same file.
/debug.logThe slash matches files only in the repository root.
debug.logBy default, patterns match files in any directory.
debug?.logThe question mark matches just one character.
debug[0-9].logSquare brackets are used to match a single character from a particular range.
debug[01].logSquare brackets match a single character from the particular set.
debug[!01].logThe exclamation mark is used to match any character except one from the particular set.
debug[a-z].logRanges can be numeric or alphabetic.
logsThe pattern will match both files and the contents of directories with that name if it isn’t used with a slash.
logs/Using a slash points out that the pattern is a directory. The whole content of any directory with its files and subdirectories in the repository which matches that name will be ignored by Git.
logs/**/debug.logA double asterisk matches zero or more directories.
logs/*day/debug.logAsterisks can be used in directory names too.

Here is a small .gitignore showing how debug?.log (the ? matches exactly one character) behaves. It ignores debug0.log and debug1.log, but not debug10.log, because 10 is two characters:

.gitignore patterns

debug?.log

# matches debug0.log, debug1.log, debug9.log
# does NOT match debug10.log (two characters)

Shared .gitignore files in the repository

You can define several .gitignore files in different directories in the repository. Each of the patterns is tested relative to the directory that contains that file. However, the simplest way is to define a single .gitignore file at the root of the repository.

As your .gitignore file is checked in, in your repository it is versioned like other files and is shared with your team when you push. You should only include patterns in .gitignore to benefit other users of the repository.

Personal rules for Git ignore

Personal ignore patterns for a single repository can be placed in the special file .git/info/exclude. Its syntax is identical to .gitignore, but because the .git directory is not part of the repository content, these rules are not versioned and are not shared when you push or clone. Use this file for editor backups, scratch files, or anything specific to your own workflow that the rest of the team should not have forced on them.

Global Git ignore rules

You can define the Git core.excludesFile property to additionally specify global Git ignore patterns for all repositories on your local system. This file is going to be created by yourself. You can put your global .gitignore file at your home directory to find it easily. Once you've created the file, configure its location with the git config command, like this:

global gitignore rules

touch ~/.gitignore
git config --global core.excludesFile ~/.gitignore

Ignoring a previously committed file

Adding a pattern to .gitignore does not stop Git from tracking a file that is already committed — ignore rules apply to untracked files only. To start ignoring such a file you must first remove it from Git's index. Use git rm with the --cached option: this stages the file's removal from the repository while keeping the copy on your disk as an ignored file. Then commit the change.

.gitignore committed files

echo debug.log >> .gitignore
git rm --cached debug.log
#rm 'debug.log'
git commit -m "Start ignoring debug.log"

If you also want the file gone from your working directory, drop --cached (git rm debug.log). Use git status afterwards to confirm the file no longer appears as tracked or untracked.

Committing an ignored file

The ignored file can be committed to the repository with the combination of the -f (or --force) option with git add. However, choose this way in case you have a general pattern, such as *.log, but you want to commit a specific file:

commiting ignored files

cat .gitignore
# *.log
git add -f debug.log
git commit -m "Force adding debug.log"

If not, the simplest way is setting an exception to the general rule:

commit ignored files

echo '!debug.log' >> .gitignore

cat .gitignore
#*.log
#!debug.log

git add debug.log
git commit -m "Adding debug.log"

Stashing an ignored file

The git stash command takes your uncommitted staged and unstaged changes, saves them away for later, and reverts your working copy to a clean state. By default it stashes only changes to tracked files — ignored and untracked files are left in place. Two options widen that scope:

  • git stash --include-untracked (or -u) also stashes untracked files.
  • git stash --all (or -a) also stashes both untracked and ignored files.
git stash --all

Debugging .gitignore files

With complicated patterns, or rules spread across multiple .gitignore files, it can be hard to tell which rule is hiding a file. The git check-ignore command with -v (or --verbose) reports the exact pattern responsible:

git check ignored files

git check-ignore -v debug.log
#.gitignore:3:*.log    debug.log

The output has four fields separated by colons (and a space before the file name):

<file containing the pattern>:<line number of the pattern>:<pattern>    <file name>

So .gitignore:3:*.log debug.log means: the rule *.log on line 3 of .gitignore is what causes debug.log to be ignored. If the command prints nothing, the file is not ignored by any rule.

  • git rm — remove files from tracking, the key to ignoring an already-committed file.
  • git add — stage files, including -f to force-add an ignored one.
  • git stash — save changes aside; combine with --all to include ignored files.
  • git config — set core.excludesFile for a global ignore list.
  • git clean — delete untracked files; pair with -x to also remove ignored ones.

Practice

Practice
Which statements accurately describe the functionalities and rules of " `.gitignore` files in Git?
Which statements accurately describe the functionalities and rules of " `.gitignore` files in Git?
Was this page helpful?