The letter A styled as Alchemists logo. lchemists
Published April 15, 2022 Updated April 15, 2022
Cover
Git Ignore

When first setting up and configuring Git, I sometimes see fellow engineers overlook — or even under appreciate — the value of your Git ignore file. Today, I want to talk about your Git ignore file both in terms of global and local configuration, the file path on your machine, and what to put in it.

Configuration

Let’s start by looking at the Git’s configuration documentation which states you can use core.excludesFile to configure where your ignore file is located:

Specifies the pathname to the file that contains patterns to describe paths that are not meant to be tracked, in addition to .gitignore (per-directory) and .git/info/exclude. Defaults to $XDG_CONFIG_HOME/git/ignore. If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/ignore is used instead. See gitignore.

This means, by default, you can define what you want to ignore via the following files:

# Global default as specified by the XDG specification.
$HOME/.config/git/ignore

# Local and unique per project
<your project path>/.gitignore

# Local and unique per project
<your project path>/.git/info/exclude

My recommendation is to put as much as you can into your global Git ignore file so you can define common directories and files in one place while reducing the maintenance burden of maintaining the same configuration across multiple projects. This can ruffle some feathers of inexperienced engineers new to your project because they might complain about multiple files showing up in their Git diff when trying to commit new changes for the first time. I look at this as an opportunity to educate and train these engineers in more of the advanced techniques of Git rather than pollute your project’s local Git ignore file. I’ll illustrate and expand upon this more in a moment. For now, let’s talk about your global ignore file first and then move on to discussing your per-project local ignore file.

Global

As documented above, the default path of your global Git ignore is going to be located here:

$HOME/.config/git/ignore

The file location adheres to the XDG specification for organizing configuration files. This is a powerful specification and I encourage you to read more about XDG if you are not familiar already. I also maintain the XDG gem (same link) which allows you to leverage the XDG specification within your own Ruby code. 🎉

Should you not want to use the XDG specification — again, I would strongly discourage you from doing this — you can always specify a custom path via the core.excludesFile setting in your global (or local) Git configuration.

As for what to put in your global ignore file, here’s what I use in case it’s of interest:

# Archives
*.7z
*.bzip
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.tar.gz
*.zip

# Bundler
.bundle

# CTags
.tags
.tags_sorted_by_file
/tags

# Databases
*.dump

# Environments
*.env*

# Logs
*.log

# macOS
.DS_Store

# SimpleCov
coverage

# Temp Directories
tmp

The source code for this can be found via my Dotfiles project, specifically my ignore file. Feel free to pilfer anything that might of use to you.

Local

As for your local ignore configuration, you have two options as stated earlier:

<your project path>/.gitignore
<your project path>/.git/info/exclude

Most projects use .gitignore because it’s safe to commit to your repository and easy for anyone working on the same project to discover what is ignored or add to it.

You can also use .git/info/exclude but anything you add here won’t be shared across the team as a whole. This can be valuable when you want to ignore something that is unique to the project, specific to you, and doesn’t effect the team. I’ve never had a need for this — yet — but your mileage may vary.

As for what to put in your local Git ignore, that definitely depends and will evolve over time. For example, when using Rubysmith to build a new Ruby project, you’ll see the following in your .gitignore:

.bundle
tmp

…​but if you opted to build a Ruby gem using Gemsmith, you’d get a slightly different .gitignore:

*.gem
.bundle
Gemfile.lock
pkg
tmp

While the above is specific to Ruby, patterns will differ per programming language used and project requirements. The one rule of thumb is that if you find you are repeating yourself, pattern-wise, then consider extracting what you have defined locally into your global ignore file.

You’ll also notice there is some duplication between what I presented in the global ignore example earlier. This was originally done to appease people new to Ruby projects but will eventually be moved to the global Git ignore configuration to improve multi-project maintenance. If nothing else, this does provide a good example of patterns ripe for deduplication.

Guidelines

With all of the above in mind, here are a few guidelines for you to follow:

  • Default to the XDG specification.

  • Extract common patterns to your global ignore file when possible.

  • When you have specific files or folders unique to you, don’t force ignoring all of these files onto the team. Use your global configuration or even .git/info/exclude within the project you are working on itself. This’ll empower you to be productive without adding unnecessary maintenance burden upon the team. A good example of this is IDE specific local folders like Visual Studio Code’s .vscode folder, RubyMine’s .idea folder, etc.

Linting

As of right now, the ability to lint and encourage common patterns isn’t provided via the Git Lint gem — another gem I maintain — but I’m thinking about how to improve upon this and encourage better practices. If you have thoughts or ideas, please reach out.

Conclusion

I hope this dive into global and local Git ignore files has been of help to you. If you let Git do all of the heavy lifting for you, you’ll be more productive with less of a maintenance burden to boot. Enjoy!