Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are leading asterisks "**/" redundant in .gitignore path matching syntax?

Are there any usages that can't be replaced by equivalents without asterisks?

Two consecutive asterisks ("**") in patterns matched against full
pathname may have special meaning:

A leading "**" followed by a slash means match in all directories.
For example, "**/foo" matches file or directory "foo" anywhere,
the same as pattern "foo". "**/foo/bar" matches file or directory
"bar" anywhere that is directly under directory "foo".

A trailing "/**" matches everything inside. For example, "abc/**"
matches all files inside directory "abc", relative to the location
of the .gitignore file, with infinite depth.

A slash followed by two consecutive asterisks then a slash matches
zero or more directories. For example, "a/**/b" matches "a/b",
"a/x/b", "a/x/y/b" and so on.

Other consecutive asterisks are considered invalid.

https://git-scm.com/docs/gitignore#_pattern_format

Let me point out, that i'm asking only about leading asterisks/slash redundancy. Since it seems any **/foo/bar can be replaced by simple foo/bar

For example, i have the following in my .gitignore file:

# NuGet Packages

# The packages folder can be ignored because of Package Restore
**/packages/*

# except build/, which is used as an MSBuild target.
!**/packages/build/

# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config

And i'm wondering, why they couldn't simply write:

# NuGet Packages

# The packages folder can be ignored because of Package Restore
packages/*

# except build/, which is used as an MSBuild target.
!packages/build/

# Uncomment if necessary however generally it will be regenerated when needed
#!packages/repositories.config

https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

like image 986
Nieralyte Avatar asked Jan 20 '17 10:01

Nieralyte


People also ask

What does double asterisk mean in Gitignore?

A trailing " /** " matches everything inside. For example, " abc/** " matches all files inside directory " abc ", relative to the location of the .gitignore file, with infinite depth. A slash followed by two consecutive asterisks then a slash matches zero or more directories.

What do you place within a .gitignore file?

gitignore file is a plain text file where each line contains a pattern for files/directories to ignore. Generally, this is placed in the root folder of the repository, and that's what I recommend. However, you can put it in any folder in the repository and you can also have multiple .

What is a trailing asterisk?

A trailing asterisk (*) indicates that a DISPLAY command applies to all jobs or started tasks that match a leading character string. The DISPLAY JOBS, J, A, or TS command supports only a trailing asterisk. You cannot specify an asterisk in other character positions in job or started task names.

How do I ignore a .gitignore file?

If you want to ignore a file that you've committed in the past, you'll need to delete the file from your repository and then add a . gitignore rule for it. Using the --cached option with git rm means that the file will be deleted from your repository, but will remain in your working directory as an ignored file.


2 Answers

No, the leading **/ is only obsolete if the remaining pattern does not contain a slash except for a trailing one.

The documentation at https://git-scm.com/docs/gitignore is a bit misleading in my opinion, as it states

If the pattern does not contain a slash /, Git treats it as a shell glob
pattern and checks for a match against the pathname relative to the
location of the .gitignore file (relative to the toplevel of the work
tree if not from a .gitignore file).

but actually matches only against the name of a file or directory, not the whole path.

So **/packages/build matches packages/build in any depth.
packages/build as it contains a slash is effectively the same as /packages/build and only matches packages/build on the same level as the ignore file.

On the other hand build matches build in any depth so is effectively the same as **/build.
Whereas /build only matches build on the same level as the ignore file.

It always depends on whether the pattern (after removing a trailing slash if present) contains any slashes or not.

like image 183
Vampire Avatar answered Oct 05 '22 08:10

Vampire


There was (but isn't any more, thanks to editing) a faulty assumption in the question. To demonstrate the issue:

$ mkdir tignore
$ cd tignore
$ git init
Initialized empty Git repository in .../tignore/.git
$ git status -uall --short
$ mkdir sub sub/foo; touch sub/foo/bar; echo foo/bar > .gitignore; git status -uall -s
?? .gitignore
?? sub/foo/bar
$ echo '**/foo/bar' > .gitignore; git status -uall -s
?? .gitignore
$ 

In other words, to get Git to ignore the file foo/bar within subdirectory sub, we had to write **/foo/bar in the top level .gitignore, because foo/bar does not match sub/foo/bar.

Note that the rules are different for ignore entries that do not contain an embedded slash. That is:

$ echo bar > .gitignore
$ git status -uall -s
?? .gitignore
$ 

Here we do not need the leading **/. So leading **/ is redundant when the name to be ignored does not contain its own embedded /, but is not redundant when the name to be ignored does contain its own embedded /.

For a longer treatment of the somewhat odd .gitignore rules, see gitignore rules (applied to a codeigniter stack).

like image 22
torek Avatar answered Oct 05 '22 08:10

torek