Excluding from version control

Author

Marie-Hélène Burle

This workshop looks in more details at what and how to exclude from version control.

What to exclude

There are files you really want to put under version control, but there are files you shouldn’t.

Put under version control:

  • Scripts
  • Manuscripts and notes
  • Makefile & similar

Do NOT put under version control:

  • Non-text files (e.g. images, office documents)
  • Outputs that can be recreated by running code (e.g. graphs, results)

How to exclude

The .gitignore file

To exclude files from version control, create a file called .gitignore in the root of your project and add those files to it, one per line.

Example:

# Create .gitignore and add 'graph.png' to it
echo graph.png > .gitignore

# `>` would overwrite the content. `>>` appends
echo output.txt >> .gitignore

# You can also ignore entire directories
echo /result/ >> .gitignore

Globing patterns

You can use globbing patterns.

Example:

# Exclude all .png files
echo *.png >> .gitignore

.gitignore syntax

Each line in a .gitignore file specifies a pattern.

Blank lines are ignored and can serve as separators for readability.

Lines starting with # are comments.

To add patterns starting with a special character (e.g. #, !), that character needs to be escaped with \.

Trailing spaces are ignored unless they are escaped with \.

! negates patterns.

Patterns ending with / match directories. Otherwise patterns match both files and directories.

/ at the beginning or within a search pattern indicates that the pattern is relative to the directory level of the .gitignore file (usually the root of the project). Otherwise the pattern matches anywhere below the .gitignore level.

Examples:

/foo/bar/ matches the directory foo/bar, but not the directory a/foo/bar
foo/bar/ matches both the directories foo/bar and a/foo/bar

* matches anything except /.

? matches any one character except /.

The range notation (e.g. [a-zA-Z]) can be used to match one of the characters in a range.

A leading **/ matches all directories.

Example:

**/foo matches file or directory foo anywhere. This is the same as foo.

A trailing /** matches everything inside what it precedes.

Example:

abc/** matches all files (recursively) inside directory abc

/**/ matches zero or more directories.

Example:

a/**/b matches a/b, a/x/b, and a/x/y/b