Imagine you have the following tree structure:
.
├── cmd
│ └── fastly
├── fastly
You want to avoid commiting the fastly
file in the root, but you're OK with cmd/fastly
being committed.
To achieve this we need to use a specific wildcard glob that at first glance appears unintuitive:
**/fastly
!cmd/fastly
What the first line does is match both ./fastly
and ./cmd/fastly
, while the second line allows you to negate the ./cmd/fastly
.
Originally, the first line was set to fastly
but it turns out if you do that, the second line will no longer work because the first line is matched anywhere in the path, and that means gitignore cannot negate files inside an an already ignored directory (which this would do, i.e. fastly
isn't ignoring the root fastly
file, it's ignoring anything that contains fastly
).
The reason **/fastly
didn't immediately spring to mind for me is because I read it as matching any subdirectory containing fastly
(e.g. it would match cmd/fastly
), when in fact the **/
is misleading because it will match either ./
or <some-directory-name>/
and that's why it works to match ./fastly
and ./cmd/fastly
and thus we can safely negate the second line of our gitignore, because we've not just blanket ignored every possible folder containing fastly
, we have this time in fact constrained our match to include the root file.