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)
|