How to use .gitignore correctly

The Most Important Use Cases

First things first, how can we exclude every target folder created by Maven in every sub-module?

The answer is very easy: target/
This will match any directory (but not files, hence the trailing /) in any subdirectory relative to the .gitignore file. This means we don’t even need any * at all.

Here is an overview of the most relevant patterns:

.gitignore entry Ignores every…
target/ folder (due to the trailing /) recursively
target file or folder named target recursively
/target file or folder named target in the top-most directory (due to the leading /)
/target/ folder named target in the top-most directory (leading and trailing /)
*.class …every file or folder ending with .class recursively

Advanced Use Cases

For more complicated use cases refer to the following table:

.gitignore entry Ignores every…
#comment …nothing, this is a comment (the first character is a #)
\#comment …every file or folder with name #comment (\ for escaping)
target/logs/ …every folder named logs which are a subdirectory of a folder named target
target/*/logs/ …every folder named logs two levels under a folder named target (* doesn’t include /)
target/**/logs/ …every folder named logs somewhere under a folder named target (** includes /)
*.py[co] …file or folder ending in .pyc or .pyo. However, it doesn’t match .py!
!README.md Doesn’t ignore any README.md file even if it matches an exclude pattern, e.g. *.md.
NOTE This does not work if the file is located within an ignored folder.

Examples

Maven-based Java project

target/
*.class
*.jar
*.war
*.ear
*.logs
*.iml
.idea/
.eclipse

Important Dot Files in Your Home Folder

# ignore everything ...
/*
# ... but the following
!/.profile
!/.bash_rc
!/.bash_profile
!/.curlrc

Wait, There’s More

There are several locations where Git looks to ignore files. Besides looking in the root folder of a Git project, Git also checks if there is a .gitignore in every subdirectory. This way you can ignore files on a finer grained level if different folders need different rules.

Moreover, you can define repository specific rules which are not committed to the Git repository, i.e. these are specific to your local copy. These rules go into the file .git/info/exclude which is created by default in every Git repository with no entries.

One useful file you can define yourself is a global ignore file. It doesn’t have a default location or file name. You can define it yourself with the following command:

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

Every rule which goes into this file applies to every Git repository in your user account. This is especially useful for OS-specific files like .DS_Store on MacOS or thumbs.db on Windows.

Conclusion

As we have seen it is fairly easy to ignore files and folders for the typical use cases. Even though ignore rules don’t support regex, gitignore is highly flexible and can be adapted to more complicated project structures using unix globs and different files on different levels.

So now you know. Go ahead, rework your existing .gitignore files and add a global ignore file to you system!

More Resources

For each and every detail on gitignore refer to these resources.