How to exclude files from being tracked by Git

Updated: January 27, 2024 By: Guest Contributor Post a comment

Introduction

Version control with Git is essential for managing changes to source code over time. However, not all files and directories in a project should be tracked by Git. Sensitive information such as passwords, user-specific configurations, and intermediate build artifacts usually need to be excluded to avoid publishing them to a public repository or cluttering up the commit history.

In this tutorial, we’ll explore various ways to exclude files and directories from being tracked by Git using examples ranging from basic to advanced. You’ll learn to fine-tune what Git tracks in your projects, enhancing the security and cleanliness of your repositories.

Understanding .gitignore

The primary method of specifying ignored files is through a file named .gitignore. This file can be placed in the repository’s root or within any directory to address files within that directory and its subdirectories. Inside .gitignore, you can specify filenames, directory names, wildcard patterns, and even use negation to have exceptions in the ignoring rules.

Basic Syntax:

# Comment

*.log
secrets/
*.tar.gz
!important.log

Action:

git status
# You will observe that files matching the patterns in .gitignore are untracked

Global .gitignore

If you have files that you want to ignore across all your repositories (such as OS-related files, IDE settings, etc.), you can create a global .gitignore file.

Basic Setup:

touch ~/.gitignore_global
# Add general ignore patterns
echo '*.DS_Store' >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global

Action:

git status
# .DS_Store files will now be globally ignored.

Excluding Local Files Without Changing .gitignore

Sometimes, you might wish to ignore files only on your local machine without affecting other collaborators. In such cases, you can use the repository’s .git/info/exclude file to define what should be ignored.

# Example of ignoring just for local:
echo 'local_config.yml' >> .git/info/exclude

Action:

git status
# local_config.yml will now be ignored on your machine

Ignoring Tracked Files

If a file is already being tracked by Git, adding it to .gitignore will not remove it from version history or prevent Git from tracking it. To stop tracking a file that is already in the index, you must explicitly remove it using git rm --cached.

git rm --cached sensitive_file.txt
git commit -m 'Stop tracking sensitive_file.txt'

Action:

git status
# sensitive_file.txt is no longer tracked but still exists in your working directory

Exclude Folders and Git Submodules

When excluding whole folders, you have to ensure that the folder name ends with a slash in the .gitignore file. Moreover, if that directory is a Git submodule, you’ll need additional consideration to how you manage the submodule.

submodule_dir/

Action:

git status
# The entire 'submodule_dir/' directory is ignored

Patterns and Wildcards

The .gitignore can include patterns that make it possible to ignore complex file structures with a single line. Here are some common patterns:

  • * to match any number of characters
  • ? to match one character
  • [abc] to match any character inside the brackets
  • **/ to match any level of subdirectory

Pattern Uses:

*.swp
project/?/temporary/
backup.????-??-??
**/build/

Action:

git status
# Files like '.swp', 'backup.2023-03-10', and directories under 'project/a/temporary/' or 'any_subdir/build/' are ignored

Ignoring Files Based on Attributes

You can also ignore files based on file attributes using a .gitattributes file. This is an advanced feature and allows finer control over files’ attributes such as diffing, merging, or automatic end-of-line normalization.

Example:

*.bin -diff
some_path/* text=auto eol=lf

Action:

# Binary files (*.bin) won't have their differences shown during commits
# Files in 'some_path' will normalize end-of-line to LF

Conclusion

In this tutorial, we have seen how to effectively exclude files from being tracked in Git, which is indispensable for any developer aiming to maintain a clean and secure codebase. Whether using .gitignore, local excludes, global ignores, or special attribute configurations, we now have the means to customize our Git behaviors to suit our specific use cases.