Unignore subdirectories of ignored directories in Git

Wil picture Wil · Mar 10, 2011 · Viewed 48.1k times · Source

Let's say I have ignored a directory, but I want to unignore specific subdirectories therein. So I have the setup:

/uploads/
/uploads/rubbish/
/uploads/rubbish/stuff/KEEP_ME/
/uploads/foo/
/uploads/foo/bar/lose/

And I want to ignore everything but the KEEP_ME directory. I would hope the ignore would look something like:

/uploads/*
!/uploads/rubbish/stuff/KEEP_ME/

But that's not working, and neither are several permutations on the same theme.

One that does work is

/uploads/**/**/**/
!/uploads/rubbish/stuff/KEEP_ME/

But that feels a little restrictive and verbose?

Answer

Art Shayderov picture Art Shayderov · Mar 12, 2011

According to pattern format section of the gitignore documentation:

An optional prefix "!" which negates the pattern; any matching file excluded by a previous pattern will become included again. It is not possible to re-include a file if a parent directory of that file is excluded. Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined. Put a backslash ("\") in front of the first "!" for patterns that begin with a literal "!", for example, "!important!.txt".

Therefore the previously-excluded parent directory /uploads/rubbish/stuff/keep/ pattern must be exclusively negated before negating its content:

#ignore everything within /uploads/ 
/uploads/*

#include everything within /uploads/rubbish/stuff/keep
!/uploads/rubbish/stuff/keep/  
!/uploads/rubbish/stuff/keep/*

To include subdirectories inside /uploads/rubbish/stuff/keep/ add the third line:

!/uploads/rubbish/stuff/keep/**/*