Earlier in this chapter, you saw how to use the .gitignore file to pass over main.o, an irrelevant file. As in that example, you can skip any file by adding its name to .gitignore in the same directory. Additionally, you can ignore the file everywhere by adding it to the .gitignore file in the top-most directory of your repository.
But Git also supports a much richer mechanism. A .gitignore file can contain a list of filename patterns that specify what files to ignore. The format of .gitignore is as follows:
Blank lines are ignored, and lines starting with a
hash mark (#
) can be used for comments.
However, the hash mark does not represent a comment if it follows
other text on the line.
A simple, literal filename matches a file in any directory with that name.
A directory name is marked by a trailing slash
character (/
). This matches the named
directory and any subdirectory but does not match a file or a
symbolic link.
A pattern containing shell globbing characters, such
as an asterisk (*
), is expanded as a shell glob
pattern. Just as in standard shell globbing, the match cannot
extend across directories and so an asterisk can match only a
single file or directory name. But an asterisk can still be part
of a pattern that includes slashes to specify directory names as
part of the pattern (e.g.,
debug/32bit/*.o).
An initial exclamation point (!
) inverts
the sense of the pattern on the rest of the line. Additionally,
any file excluded by an earlier pattern but matching an inversion
rule is included. An inverted pattern overrides lower-precedence
rules.
Furthermore, Git allows you to have a
.gitignore file in any directory within your
repository. Each file affects its directory and all subdirectories. The
.gitignore rules also cascade: you can override the
rules in a higher directory by including an inverted pattern (using the
initial !
) in one of the subdirectories.
To resolve a hierarchy with multiple .gitignore directories and to allow command-line addenda to the list of ignored files, Git honors the following precedence, from highest to lowest:
Patterns specified on the command line.
Patterns read from .gitignore in the same directory.
Patterns in parent directories, proceeding upward. Hence, the current directory’s patterns overrule the parents’ patterns, and parents close to the current directory take precedence over higher parents.
Patterns from the .git/info/exclude file.
Patterns from the file specified by the configuration
variable core.excludefile
.
Since a .gitignore is treated as a regular file within your repository, it is copied during clone operations and applies to all copies of your repository. In general, you should place entries into your version-controlled .gitignore files only if the patterns apply to all derived repositories universally.
If the exclusion pattern is somehow specific to your one repository and should not (or might not) be applicable to anyone else’s clone of your repository, the pattern should instead go into the .git/info/exclude file, because it is not propagated during clone operations. Its pattern format and treatment is the same as .gitignore files.
Here’s another scenario. It’s typical to exclude .o files, which are generated from source by the compiler. To ignore .o files, place *.o in your top level .gitignore. But what if you also had a particular *.o file that was, say, supplied by someone else and for which you couldn’t generate a replacement yourself? You’d likely want to explicitly track that particular file. You might then have a configuration like this:
$cd my_package
$cat .gitignore
*.o $cd my_package/vendor_files
$cat .gitignore
!driver.o
The combination of rules means that Git will ignore all .o files within the repository but will track one exception, the file driver.o within the vendor_files subdirectory.
3.16.46.131