Tracking only a type of files in Git

Here we will show you how to track a type of files in a Git repository by writing a proper .gitignore file.

To check the result of .gitignore in the following part, we assume you have a newly initiated Git repository with below directory structure.

|-- a.conf
|-- b.h
|-- conf/
|   |-- conf.conf
|   `-- extra/
|       `-- extra.conf
`-- include/
    `-- include.h

Track only a type of files

If you want to ignore all the *.conf files under the whole repository mentioned above, the .gitignore will as below:

# goal: ignore everything except /conf/**/*.conf 

# ignore everything in the root
*.*

# exclude *.conf
!*.conf

Test the .gitignore with git status:

$ git status
On branch master

Initial commit

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

        a.conf
        conf/

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

As you see, it prompts only a.conf and conf folder are untracked, while the include folder is not mentioned for it does not contain any conf file but the conf folder does. This means only the files mentioned being untracked by git status are expected to be tracked according to the rules inside the .gitignore.

Track only a type of files under a folder

Again take the repository mentioned in the beginning for example, assuming you want to track only *.conf files under conf directory as well as its subdirectories. Write the .gitignore file like this:

# goal: ignore everything except /conf/**/*.conf 

# ignore everything in the root
/*

# exclude /conf/
!/conf/

# ignore all files in /conf and its subdirectories
/conf/**/*.*

# exclude *.conf in /conf and its subdirectories
!/conf/**/*.conf

Test the .gitignore:

$ git status
On branch master

Initial commit

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

        conf/

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

As what is expected, it only prompt the conf folder is untracked.

Stopping tracking a file in Git

To untrack a file that has been committed, what you do is adding a new ignoring rule and removing the file in a commit.

Below is a full example of ignoring /assets/my-style.css .

Step 1: add below content to .gitignore file to add an ignore rule.

/assets/my-style.css

Note: See ignoring files for how to create your  .gitignore file and write ignore rules.

Step 2: remove it from repository and commit the changes .

# Stage .gitignore
$ git add .gitignore

# Remove my-style.css file from staging area, my-style.css
# in working directory is left alone.
# --cached, only apply to staging area
$ git rm --cached -- assets/css/my-style.css

# Commit them
$ git commit

Thus, my-style.css will not be tracked any more. Be aware that it still remains in previous history.

To stop tracking a directory is similar, just replace above file with a folder in .gitignore file and git rm command.

Ignoring files in Git

Normally there are some files or folders that you do not want them to be tracked. Here you will learn how to set up various ignore rules to exclude them from git repositories.

Ignore files in a git repository

Use .gitignore to allow sharing ignore rules (version controlled)

If you want some files being untracked in a repository, create an .gitignore file at its root directory and commit it. .gitignore file is used to list all the file patterns to ignore, standard glob patterns work in it.

Basic rules for patterns have been included in below example .gitignore file :

# ignore all .class files
*.class

# Exclude lib.class from "*.class", meaning all lib.class are still tracked
!lib.class

# Ignore all json files whose name begin with 'temp-'
temp-*.json

# Only ignore the build.log file in current directory, not those in its subdirectories
/build.log

# Specify a folder with appending a slash in the end
# Below statement ignores all files in any directory named temp
temp/

# Ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# Ignore all .pdf files in the doc/ directory and any of its subdirectories
# /** matches 0 or more directories
doc/**/*.pdf

Remember to commit and push to share the rules in the repository. If you forget to do that, .gitignore will only take effect locally.

$ git add .gitignore
$ git commit -m 'chore: add .gitignore'
$ git push

Note

Adding new patterns in .gitignore won’t affect the files already tracked by Git. You can stop tracking a file.

You can have more than one .gitignore file in subdirectories. Its content will only apply to the folder it resides.

Use .git/info/exclude to ignore files locally (without sharing ignore rules)

If you just want a personal and local ignore configuration without committing a .gitignore file, use .git/info/exclude to achieve that.

What you do is just adding exclude rules in .git/info/exclude within in the root of a repository.

Any rule added in the file will not be pushed to a remote repository. This way enables you to ignore locally generated files and no need to worry about other users.

Ignore files in all repositories

If you want to ignore some files for all repositories, you can set a global .gitignore file. Below is an example to ignore .DS_Store files :

File ~/.gitignore_global :

*~
.*.swp
.DS_Store

Then configure it as your global gitignore settings in Git :

$ git config --global core.excludesfile ~/.gitignore_global

Debug gitignore files with check-ignore command

check-ignore command can be used to debug if a file/folder match some ignore rules in .gitigonre (or other input files to the exclude mechanism).

Debug ignore rule

# -v, verbose, output details about the matching pattern (if any)
# for each given pathname.
$ git check-ignore -v <pathname>

With -v, if the pathname matches an ignore pattern, it outputs the pattern’s line number, the pattern itself and your queried pathname, or it output nothing. Without -v, if some pattern matches, only the pattern is output.

Below example debugs if user.csv is excluded:

# Debug whether user.csv is exclude by some ignore rules
$ git check-ignore -v user.csv
.gitignore:3:*.csv      user.csv

Here user.csv is ignored by *.csv pattern in .gitignore.

Note: By default, tracked files are not output since they are not subject to exclude rules. If a file is tracked before and untracked currently, it can be output.

With --no-index option, it will also output files that has been tracked but ignored in .gitignore.

# Track user.csv even it has been ignored.
git add -f user.csv

# Check without --no-index, nothing is output
git check-ignore -v user.csv

# Check with --no-inxex
git check-ignore -v --no-index user.csv
.gitignore:3:*.csv      user.csv

Debug ignore and exclude rules

If user.csv is ignored by *.csv but then excluded by !user.csv in .gitignore, such as below .gitignore file.

# ignore all .csv files
*.csv

# exclude user.csv
!user.csv

Then it will only output the ignore rule.

$ git check-ignore -v user.csv
.gitignore:3:*.csv      user.csv

Note:

Compared with check-ignore command, you may just want to see whether a file is tracked. ls-files command will help you.

# Check whether user.csv is traked or not
$ git ls-files -- user.csv

# List all untrancked files excluding ignored files
$ git ls-files --others --exclude-standard

Reference

Read more

Listing untracked files in Git

List all the untracked files, including ignored files

git ls-files command is used to list files, add -o or --others to list all the untracked files:

# List all the untracked files, including the ignored files
$ git ls-files --others

List untracked files, excluding ignored files

--exclude-standard option excludes files in .gitignore, .git/info/exclude or the user’s global exclusion file.

# List untracked files, excluding the ignored files.
$ git ls-files --others --exclude-standard