Close

Git - Ignoring Files

[Updated: Dec 3, 2018, Created: Dec 2, 2018]

The files which we do not add to the staging, are categorized as untracked files by Git. Git still monitors such files and informs us about them when we use git status command.

If we want Git to completely ignore some files or folders without treating them as being untracked, we can add a file .gitignore with predefined ignore rules. These rules are superset of the standard glob pattern. The file can be added to the root of work-tree directory.

Quick Example

Joe@jpc MINGW64 ~
$ mkdir example

Joe@jpc MINGW64 ~
$ cd example

Joe@jpc MINGW64 ~/example
$ git init
Initialized empty Git repository in C:/Users/Joe/example/.git/

Joe@jpc MINGW64 ~/example (master)
$ echo some read me content > README.txt

Joe@jpc MINGW64 ~/example (master)
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        README.txt

nothing added to commit but untracked files present (use "git add" to track)

Joe@jpc MINGW64 ~/example (master)
$ echo README.txt > .gitignore

Joe@jpc MINGW64 ~/example (master)
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitignore

nothing added to commit but untracked files present (use "git add" to track)

Joe@jpc MINGW64 ~/example (master)
$ echo .gitignore >> .gitignore

Joe@jpc MINGW64 ~/example (master)
$ cat .gitignore
README.txt
.gitignore

Joe@jpc MINGW64 ~/example (master)
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

As seen above, we ignored README.txt and .gitignore itself by adding their complete names in .gitignore file.

We can have a single .gitignore file in its root directory (work-tree), which applies recursively to the entire work-tree. However, it is also possible to have additional .gitignore files in subdirectories. The rules in these nested .gitignore files apply only to the files under the directory where they are located.

Let's continue with our above example and add a subdirectory 'sub', some txt files and a .ignore file in it to ignore text files:

Joe@jpc MINGW64 ~/example2 (master)
$ ls -la
total 58
drwxr-xr-x 1 Joe 197610  0 Dec  3 00:14 ./
drwxr-xr-x 1 Joe 197610  0 Dec  2 23:08 ../
drwxr-xr-x 1 Joe 197610  0 Dec  3 00:14 .git/
-rw-r--r-- 1 Joe 197610 22 Dec  3 00:12 .gitignore
-rw-r--r-- 1 Joe 197610 21 Dec  3 00:11 README.txt

Joe@jpc MINGW64 ~/example2 (master)
$ mkdir sub

Joe@jpc MINGW64 ~/example2 (master)
$ echo a > sub/a.txt

Joe@jpc MINGW64 ~/example2 (master)
$ echo b > sub/b.txt

Joe@jpc MINGW64 ~/example2 (master)
$ git status -u
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        sub/a.txt
        sub/b.txt

nothing added to commit but untracked files present (use "git add" to track)

Joe@jpc MINGW64 ~/example2 (master)
$ echo "*.txt" > sub/.gitignore

Joe@jpc MINGW64 ~/example2 (master)
$ git status -u
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

We used -u (--untracked-files) option of status command, i.e. git status -u, without this option we cannot see the untracked files in subdirectories.

Ignore rules

Following rules are applied in .gitignore file:

  • Blank lines are ignored.
  • Line starting with # is also ignored, so it can be used to add a comment.
  • ? matches a single character.
  • * matches zero or more characters but it does not match forward slashes (e.g. a/*/z will match a/b/z but not a/b/c/z).
  • ** can match zero or more characters and forward slashes as well (e..g a/**/z will also match a/b/c/d/z).
  • To match one of the given characters, we can use square brackets e.g. [xyz] will match x or y or z but it will not match xy or yz etc.
  • To match a range use hyphen inside square brackets e.g. [0-9] will match any digit between 0 to 9, [a-z] will match any character between a to z.
  • We can avoid recursivity by starting a patterns with a forward slash (/). for example
    /README.txt
    will ignore README.txt in current directly but not in sub directories (e.g. sub/README.txt)
  • To apply a pattern on directories instead of files, we should end the pattern with forward slash (/). For example:
    .settings/
    will ignore all files and subdirectories under '.settings' folder but it will not ignore a file say src/.settings
  • ! can be used to negate a pattern. For example
    *.txt
    !tutorials/*.txt
    Will ignore all txt files except for the txt files under tutorials folder.

Using .git/info/exclude

The file .git/info/exclude (generally GIT_DIR/info/exclude) can be used to add ignore rules for local use only. The files .gitignore files are placed under work-tree so they can be committed and shared among different users, whereas .git/info/exclude file cannot be shared. Let's see an example:

Joe@jpc MINGW64 ~
$ mkdir example3

Joe@jpc MINGW64 ~
$ cd example3

Joe@jpc MINGW64 ~/example3
$ git init
Initialized empty Git repository in C:/Users/Joe/example3/.git/

Joe@jpc MINGW64 ~/example3 (master)
$ cat .git/info/exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

Joe@jpc MINGW64 ~/example3 (master)
$ echo "*.log" >> .git/info/exclude

Joe@jpc MINGW64 ~/example3 (master)
$ cat .git/info/exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
*.log

Joe@jpc MINGW64 ~/example3 (master)
$ echo x > a.log

Joe@jpc MINGW64 ~/example3 (master)
$ ls -la
total 53
drwxr-xr-x 1 Joe 197610 0 Dec  3 01:03 ./
drwxr-xr-x 1 Joe 197610 0 Dec  3 01:01 ../
drwxr-xr-x 1 Joe 197610 0 Dec  3 01:03 .git/
-rw-r--r-- 1 Joe 197610 2 Dec  3 01:03 a.log

Joe@jpc MINGW64 ~/example3 (master)
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Using config core.excludesfile

The config property core.excludesfile (configuration tutorial) can be used to specify a file location containing the ignore rules.

Let's see an example where we are going to add ignore rules globally:

Joe@jpc MINGW64 ~
$ mkdir my-git-config

Joe@jpc MINGW64 ~
$ echo "*.log" > my-git-config/my-git-ignore-rules

Joe@jpc MINGW64 ~
$ cat my-git-config/my-git-ignore-rules
*.log

Joe@jpc MINGW64 ~
$ git config --global core.excludesfile ~/my-git-config/my-git-ignore-rules

Joe@jpc MINGW64 ~
$ git config --global --list
user.name=Joe
user.email=joe@example.com
alias.root=!pwd
core.excludesfile=C:/Users/Joe/my-git-config/my-git-ignore-rules

Joe@jpc MINGW64 ~
$ mkdir example4

Joe@jpc MINGW64 ~
$ cd example4

Joe@jpc MINGW64 ~/example4
$ git init
Initialized empty Git repository in C:/Users/Joe/example4/.git/

Joe@jpc MINGW64 ~/example4 (master)
$ echo a > mylog.log

Joe@jpc MINGW64 ~/example4 (master)
$ ls -la
total 53
drwxr-xr-x 1 Joe 197610 0 Dec  3 01:14 ./
drwxr-xr-x 1 Joe 197610 0 Dec  3 01:14 ../
drwxr-xr-x 1 Joe 197610 0 Dec  3 01:14 .git/
-rw-r--r-- 1 Joe 197610 2 Dec  3 01:14 mylog.log

Joe@jpc MINGW64 ~/example4 (master)
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

See Also