I supposed this to do the trick:
*
!/dir1/
!/dir2/
!/file1
!/file2
But to my surprise, it didn't. It seems to work if I prepend a slash before the asterisk. But I don't really understand why it doesn't work before this change. Could anybody point out?
To use negating patterns
!
in.gitignore
, just remember 2 rules.Rule 1. Files and directories are separatedly handled in the patterns. To include a directory back doesn't mean its child files/directories are also included back.
I.E. The goal is to exclude all files/directories except everything inside
/dir1
. The following does NOT work.Why? The reason is just the first rule. Though the directory
dir1
is included again, but not all its child files/directories. And only including the directory without its children means nothing to git, since git won't track empty folders.As a comparison, the following works.
Why? Because
/*
only matches the files/directories under the root directory directly, but not ignores any files/directories under sub-directories such asdir1
here. After!/dir1/
includesdir1
back, all its child files/directories are back naturely.Someone may ask, if so, why the following doesn't work, since
!/dir1/**
will includes all child files/directories ofdir1
back?The reason is in rule 2.
Rule 2. It won't include files/directories back if their parent directory is still ignored. For this rule, please read my answer to a SO question first.
That's why the previous patterns won't work. And if we add another negating pattern to include the parent directory
dir1
back first, it works.After understanding the 2 rules, the solutions for OP's case is quite straightforward.
The following works.
And the following also works.
To make it simple as follows.