.gitignore: Ignore Files and Folders in Git

By 

•

Updated on

•

11 min read

Git logo with the .gitignore title, a folder, and a file icon

When you work in a Git repository, you often create files that should stay on your machine: logs, dependency folders, build output, editor settings, and local environment files. Adding those paths to .gitignore keeps them out of commits and away from the remote repository.

The .gitignore file tells Git which untracked files and folders to ignore. This guide explains the most useful .gitignore patterns, including how to ignore a folder, how to stop tracking a committed file, and how to debug rules that do not behave as expected.

Quick Reference

For a printable quick reference, see the Git cheatsheet .

TaskPattern or command
Ignore a folder anywherefolder_name/
Ignore a folder in the repository root/folder_name/
Ignore all logs*.log
Re-include a file!important.log
Stop tracking a committed filegit rm --cached file
Stop tracking a committed foldergit rm -r --cached folder/
Force-add an ignored filegit add -f file
Check why a path is ignoredgit check-ignore -v path/to/file
Show individual ignored filesgit status --ignored --untracked-files=all

Creating a .gitignore File

Git does not have a separate command for ignoring files. You add patterns to a plain text file named .gitignore, usually in the root of the repository.

To create the file, navigate to the repository root and run:

Terminal
touch .gitignore

You can open the file in your text editor and add one pattern per line. To append a single pattern from the command line, use echo with the >> operator:

Terminal
echo "node_modules/" >> .gitignore

The .gitignore file is a normal file in the repository. Commit it so everyone who clones the project uses the same rules:

Terminal
git add .gitignore
git commit -m "Add .gitignore"

Ignore a Folder with .gitignore

To ignore a folder anywhere in the repository, add the folder name followed by a slash:

gitignore
logs/

The trailing slash tells Git to match only directories. This pattern ignores logs/, app/logs/, and any other directory with that name below the .gitignore file.

To ignore only a folder in the repository root, start the pattern with a slash:

gitignore
/dist/

This ignores dist/ at the root of the repository, but it does not ignore app/dist/.

If you need to keep an otherwise empty folder in the repository, ignore the folder contents and re-include a placeholder file:

gitignore
logs/*
!logs/.gitkeep

Git does not track empty directories, so .gitkeep is a common placeholder file. It is not a special Git feature.

If the folder was already committed before you added it to .gitignore, remove it from the Git index first:

Terminal
git rm -r --cached logs/

The --cached option keeps the folder in your working tree and removes it only from Git tracking.

What Files to Ignore

Ignored files are usually platform-specific files or automatically created files from the build systems. Some common examples include:

  • Runtime files such as log, lock, cache, or temporary files.
  • Files with sensitive information, such as passwords or API keys.
  • Compiled code, such as .class or .o.
  • Dependency directories, such as /vendor or /node_modules.
  • Build directories, such as /public, /out, or /dist.
  • System files like .DS_Store or Thumbs.db.
  • IDE or text editor configuration files.

.gitignore Syntax and Patterns

.gitignore is a plain text file in which each line contains a pattern for files or directories to ignore.

It uses globbing patterns to match filenames with wildcard characters. If you have files or directories containing a wildcard character, you can use a single backslash (\) to escape it.

Comments

Lines starting with a hash mark (#) are comments and are ignored. Empty lines can be used to improve the readability of the file and to group related lines of patterns.

Slash

The slash symbol (/) represents a directory separator. Where the slash appears in the pattern changes what the pattern matches.

If the pattern contains a slash at the beginning or in the middle, it is relative to the directory where the .gitignore resides. In the root .gitignore, /dist matches only dist in the repository root. In app/.gitignore, the same pattern matches app/dist.

If the pattern does not contain a slash, or has only a trailing slash, it matches files and directories in any directory or subdirectory.

If the pattern ends with a slash, it matches only directories. When a directory is ignored, all of its files and subdirectories are also ignored.

PatternExample matchesDoes not match
/distdistapp/dist
distdist
app/dist
doc/frotzdoc/frotza/doc/frotz
logs/logs/
app/logs/
a file named logs

A pattern such as doc/frotz often surprises people. It contains a slash in the middle, so Git anchors it to the directory of the .gitignore file. To match frotz inside any doc directory, use **/doc/frotz.

Literal File Names

The most straightforward pattern is a literal file name without any special characters.

PatternExample matches
/access.logaccess.log
access.logaccess.log
logs/access.log
var/logs/access.log
build/build

Wildcard Symbols

* - The asterisk symbol matches zero or more characters, except the slash (/).

PatternExample matches
*.logerror.log
logs/debug.log
build/logs/error.log

The *.log pattern matches in subdirectories for a different reason: it has no slash. The asterisk itself stops at directory boundaries. For example, a*frotz does not match a/doc/frotz.

** - Two adjacent asterisk symbols match across directories. A leading **/ matches in all directories, a trailing /** matches everything inside a directory, and /**/ in the middle matches zero or more directories.

PatternExample matches
logs/**Matches anything inside the logs directory.
**/buildvar/build
pub/build
build
foo/**/barfoo/bar
foo/a/bar
foo/a/b/c/bar

? - The question mark matches any single character.

PatternExample matches
access?.logaccess0.log
access1.log
accessA.log
foo??fooab
foo23
foo0s

Square Brackets

[...] - Matches any of the characters enclosed in the square brackets. When two characters are separated by a hyphen - it denotes a range of characters. The range includes all characters that are between those two characters. The ranges can be alphabetic or numeric.

If the first character following the [ is an exclamation mark (!), then the pattern matches any character except those from the specified set.

PatternExample matches
*.[oa]file.o
file.a
*.[!oa]file.s
file.1
file.0
access.[0-2].logaccess.0.log
access.1.log
access.2.log
file.[a-c].outfile.a.out
file.b.out
file.c.out
file.[a-cx-z].outfile.a.out
file.b.out
file.c.out
file.x.out
file.y.out
file.z.out
access.[!0-2].logaccess.3.log
access.4.log
access.Q.log

Negating Patterns

A pattern that starts with an exclamation mark (!) negates (re-includes) any file that is ignored by a previous pattern.

PatternExample matches
*.log
!error.log
error.log or logs/error.log will not be ignored

You cannot re-include a file if its parent directory is excluded. Git does not look inside an ignored directory, so the negation never gets a chance to match. The following rules still ignore logs/.gitkeep:

gitignore
logs/
!logs/.gitkeep

To make the negation work, ignore the directory contents instead of the directory itself:

gitignore
logs/*
!logs/.gitkeep

If a file name really starts with an exclamation mark, escape it with a backslash, for example \!important.txt.

.gitignore Example

Below is an example of what your .gitignore file could look like:

gitignore
# Ignore the node_modules directory
node_modules/

# Ignore Logs
logs
*.log

# Ignore the build directory
/dist

# The file containing environment variables
.env

# Ignore IDE specific files
.idea/
.vscode/
*.sw*

Local .gitignore

A local .gitignore file is usually placed in the repository’s root directory. However, you can create multiple .gitignore files in different subdirectories in your repository. The patterns in the .gitignore files are matched relative to the directory where the file resides.

Patterns defined in the files that reside in lower-level directories (sub-directories) have precedence over those in higher-level directories. For example, a logs/.gitignore containing !debug.log will re-include debug.log even if the root .gitignore ignores *.log.

Local .gitignore files are shared with other developers and should contain patterns that are useful for all other users of the repository.

Personal Ignore Rules

Patterns that are specific to your local repository and should not be distributed to other repositories should be set in the .git/info/exclude file.

For example, you can use this file to ignore generated files from your personal project tools.

Global .gitignore

Git also allows you to create a global .gitignore file, where you can define ignore rules for every Git repository on your local system.

Unless core.excludesFile is configured, Git reads $XDG_CONFIG_HOME/git/ignore. If XDG_CONFIG_HOME is unset or empty, it uses ~/.config/git/ignore instead.

To create the file in the default location when XDG_CONFIG_HOME is unset or empty, run:

Terminal
mkdir -p ~/.config/git
touch ~/.config/git/ignore

Alternatively, you can set a custom path. For example, to use ~/.gitignore_global as the global Git ignore file:

  1. Create the file :

    Terminal
    touch ~/.gitignore_global
  2. Add the file to the Git configuration:

    Terminal
    git config --global core.excludesfile ~/.gitignore_global
  3. Open the file with your text editor and add your rules to it.

Global rules are particularly useful for ignoring files that you never want to commit, such as files with sensitive information or compiled executables.

Ignoring Previously Committed Files

The files in your working copy can be either tracked or untracked.

To ignore a file that has been previously committed, you need to unstage and remove the file from the index, and then add a rule for the file in .gitignore:

Terminal
git rm --cached filename

The --cached option tells Git not to delete the file from the working tree but only to remove it from the index.

To recursively remove a directory, use the -r option:

Terminal
git rm -r --cached directory

If you want to remove the file from both the index and local filesystem, omit the --cached option.

When recursively deleting files, use the -n option to perform a “dry run” and show you what files will be removed:

Terminal
git rm -r --cached -n directory

The removal is staged like any other change. Commit it together with the updated .gitignore:

Terminal
git add .gitignore
git commit -m "Stop tracking directory"
Warning

The file stays in your working tree, but other developers lose it. When they pull this commit, Git deletes the file from their working copies. Back up any local configuration files before pulling, or ask the team to do so.

Removing a file from the index does not remove it from earlier commits. If passwords or API keys were committed and exposed, revoke or rotate them.

To force-add a file that is currently ignored by .gitignore, use the -f flag:

Terminal
git add -f ignored-file.log

If you need to remove untracked files from your working tree, see our guide on how to remove untracked files in Git .

Debugging .gitignore File

Sometimes it can be challenging to determine why a specific file is being ignored, especially when you are using multiple .gitignore files or complex patterns. This is where the git check-ignore command with the -v option, which tells Git to display details about the matching pattern, comes in handy.

For example, to check why the www/yarn.lock file is ignored you would run:

Terminal
git check-ignore -v www/yarn.lock

The output shows the path to the gitignore file, the number of the matching line, and the actual pattern.

output
www/.gitignore:31:/yarn.lock	www/yarn.lock

The command also accepts more than one filename as arguments, and the file does not have to exist in your working tree.

If git check-ignore prints nothing for a file that matches a pattern, the file is probably tracked. Ignore rules do not apply to tracked files, and the command skips them by default. Add the --no-index option to see the matching pattern anyway:

Terminal
git check-ignore -v --no-index path/to/file

Displaying All Ignored Files

The git status command with the --ignored option shows ignored files and directories. Add --untracked-files=all to list individual files inside ignored directories:

Terminal
git status --ignored --untracked-files=all

FAQ

Why is my file still tracked after adding it to .gitignore?
Git only ignores untracked files. If a file is already tracked, remove it from the index with git rm --cached file.

Where should I put project-specific rules?
Use a local .gitignore in the repository so everyone on the team shares the same ignore rules.

How do I ignore files only on my machine?
Add patterns to .git/info/exclude or configure a global ignore file with core.excludesfile.

How can I see which rule is matching?
Run git check-ignore -v path/to/file to display the matching pattern and file.

Is there a git ignore command?
No. Git has no built-in git ignore command. You ignore files by adding patterns to .gitignore, .git/info/exclude, or the global ignore file.

What does ! mean in .gitignore?
A leading exclamation mark negates a pattern. It re-includes a file that an earlier pattern ignored, as long as the parent directory itself is not ignored.

Conclusion

The .gitignore file allows you to exclude files from being checked into the repository. The file contains globbing patterns that describe which files and directories should be ignored.

To get started quickly, GitHub maintains a collection of useful .gitignore templates at github/gitignore . You can also use gitignore.io to generate .gitignore files for your operating system, programming language, or IDE.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page