:::: MENU ::::

Whitelisting subdirectories using Git’s .gitignore

Git’s handling of directories and wildcards doesn’t follow bash conventions. First glance at a .gitignore file can easily mislead you into thinking that typical directory references will work recursively and allow whitelisting of many directories at a time. But directories don’t really exist for Git, or at least not as you’d expect.

Here’s how to whitelist a subdirectory multiple directories deep in your file-structure, keeping all other files and directories blacklisted.

The problem

Assume that we’re working on a WordPress plugin on a local development server, and that we want Git to only track changes to our plugin, and not to WordPress core files, or other installed plugins. Note the following directories (all paths are relative to the repository root):
wp-includes # we want to ignore this core wordpress dir
wordpress/wp-content/ # a parent of the dir we want to track
wordpress/wp-content/plugins/ # also a parent of the dir we want to track
wordpress/wp-content/plugins/my-new-plugin # the dir we want to track

Of these, all should be ignored except for the last — we only need to track changes to files in “my-new-directory/”. The following .gitignore file might be your first attempt. This won’t work:
# contents of .gitignore -- won't work
* # ignore everything
!wp-content/wp-content/plugins/my-new-plugin/* # whitelist the contents

The above will result in all files being ignored, including the ones we want to track.

The solution

Every directory between the repository root and the subdirectory that should be tracked must be whitelisted separately, without recursion, and with trailing slashes, plus an additional recursive path to that subdirectory, in order to whitelist its contents. Here’s what that looks like:
# contents of .gitignore -- works
* # ignore everything
!wp-content # whitelist parent directory
!wp-content/plugins # whitelist the other parent directory
!wp-content/plugins/my-new-plugin # whitelist the actual directory
!wp-content/plugins/my-new-plugin/* # whitelist the contents

Good luck adapting this to your needs; improvements and extensions welcome!

So, what do you think ?