Git .gitignore: Excluding a folder but including a subfolder

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

Understanding .gitignore in Git

When working with Git, a version control system, it’s often necessary to exclude certain files or directories from being tracked. This is where the .gitignore file becomes indispensable. It instructs Git to ignore files that are not necessary to track, such as local configuration files or dependencies like node_modules. But what if you want to exclude a folder, yet include one of its subfolders? This tutorial dives into how to configure .gitignore to handle such cases.

Basic .gitignore Syntax

Prior to diving into complex patterns, let’s start with basic rules to craft .gitignore entries:

  • Blank lines for spacing.
  • # for commenting.
  • A standalone asterisk (*) to match any number of characters.
  • The slash (/) to denote directory paths.
  • ! to negate a pattern (including files or folders).
# Ignore all files in log directory
log/*

# Ignore a single file
my_bad_file.txt

Excluding a folder in .gitignore

Excluding a folder in Git is straightforward. Simply add the folder name followed by a forward slash to your .gitignore file:

secret_folder/

With the above rule, Git will ignore every file and subfolder inside secret_folder.

Including Specific Subfolder

To include a specific subfolder while still ignoring the rest of the folder, you can use the negation operator !. Here’s how:

# Ignoring everything in the folder
folder_to_ignore/*

# But including subfolder
!folder_to_ignore/subfolder_to_track/

Please note, the negated pattern must come after the pattern that excludes the entire folder.

Example Scenario

Let’s assume we have a directory called assets that contains many subdirectories and files, but we want Git to only track the assets/icons folder. Our .gitignore file would look like this:

# Ignore entire assets directory
assets/*

# Except the icons subdirectory
!assets/icons/

At this point, assets/icons and all its contents are trackable by Git. However, there’s a catch here.

Subfolder Content Tracking

By default, negating a subfolder does not make Git track the content inside this subfolder. You need to specify that explicitely. If the icons directory has files inside it, the following additional rules are needed:

# Explicitly track files in the icons subdirectory
!assets/icons/*

Now, Git will track every file inside the icons subfolder.

Advanced Patterns

Beyond simple inclusions and exclusions, .gitignore supports pattern matching for more complex scenarios:

  • Use asterisks as wildcards to ignore file types.
  • Double asterisks to match any number of directories.
  • Brackets for ranges or sets of characters.
# Ignoring all .log files in any subdirectory
**/*.log

# Including only png files in a subdirectory
!assets/icons/*.png

The above setup ignores all log files regardless of their location while including only PNG files within the assets/icons subfolder.

Exception Gotchas

When using exceptions, it’s important to remember that the specificity of your patterns plays a significant role. If you’re too generic, you might end up tracking files unintentionally. Always confirm that your rules do what you expect by using:

git status

This command will show you what’s currently tracked or ignored.

Case Sensitivity

The .gitignore is case sensitive. This behavior might vary depending on your filesystem, but it’s best to assume case sensitivity to avoid confusion:

# Ignore .JPEG but not .jpeg
*.JPEG

Testing Your .gitignore Rules

To check if a specific file is ignored, you can use the following command:

git check-ignore -v /path_to_file

If the file is ignored, Git will return the rule from the .gitignore file that’s causing the file to be ignored.

Conclusion

Mastering .gitignore empowers developers to maintain a clean repository by tracking only what’s necessary. Remember the order of your rules matters, and always verify your settings with git status or git check-ignore -v.