Reputation: 10594
test/test/build64/ALL_BUILD.vcxproj
The file above is ignored using following pattern:
build64/
But, the pattern below doesn't work.
build64/*
Upvotes: 3
Views: 59
Reputation: 489073
The key difference is that build64
does not have a slash in it.
I know you actually wrote build64/
and build64/*
, and build64/
does have a slash in it, but build64
does not have a slash in it and that's what makes all the difference.
Have a look at the gitignore documentation and scan down to the section headed with PATTERN FORMAT. Note the bullet point that begins with:
- If the pattern ends with a slash, it is removed for the purpose of the following description ...
The rest of the text is, I think, very confusing—too confusing—but the key here is that build64/
has its ending slash removed first, so that it doesn't have a slash in it any more. So now, if Git encounters a file named test/test/build64/ALL_BUILD.vcxproj
, Git breaks that name into four file name components, which are:
test
(the first test
in test/test
);test
(the second test
in test/test
);build64
; andALL_BUILD.vcxproj
.Does any one of these four components match build64
? Why yes, the third component does match build64
. The original build64
had a suffix slash, so is that component a directory name rather than a file name? Yes, it is: so test/test/build64/ALL_BUILD.vcxproj
is ignored by the rule build64/
, which does not contain a slash except for that ending slash that does not count.
On the other hand, if you write build64/*
, Git does not remove the slash, so the pattern includes a slash. Git breaks down the full name test/test/build64/ALL_BUILD.vcxproj
exactly as before, but this time, it requires that all those name components match the complete pattern. Do all four of the name components match build64/*
? Well, build64/*
starts with build64
, and the first name component is test
. This does not match so the match as a whole immediately fails.
Note that if you were to write test/test/build64/*
as your .gitignore
line, Git would match test/test/build64/ALL_BUILD.vcxproj
against test/test/build64/*
. Now the first component test
must match test
—it does—and the second component must also match test
, which of course it does as well. The third component must match build64
and the last component, ALL_BUILD.vcxproj
, must match *
. All of these requirements are met, so this would select the file to make Git shut up about untracked-ness.
You could also write **/build64/*
, because **
matches any number of leading components. This would match the full name test/test/build64/ALL_BUILD.vcxproj
, but also build64/file
, fred/build64/wilma
, and fred/wilma/build64/betty
. Note that it would not match fred/wilma/build64/barney/betty
because barney/betty
has too many components—but if you match the directory fred/wilma/build64/barney
, Git may never bother to look inside fred/wilma/build64/barney/
to find betty
anyway.
In any case, it's important to remember that shell-style matching is done one file name component at a time, except for the **
matches. The "all must match" rule is triggered by a gitignore pattern that includes an embedded slash; otherwise only one component must match. Trailing slashes are, as the documentation almost says,
removed for the purpose of
deciding whether to use the "all must match" or "only one must match" rule.
Upvotes: 2