git .gitignore 语法:bin vs bin/ vs. bin/* vs. bin/**
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8783093/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
.gitignore Syntax: bin vs bin/ vs. bin/* vs. bin/**
提问by chandsie
What's the difference between adding bin
, bin/
, bin/*
and bin/**
in my .gitignore file? I've been using bin/
, but looking at other.gitignore files(in the eclipse filethe double and single star are even used together like this: tmp/**/*
what's up with that?) I see that the first two patterns are also widely used as well. Can someone please explain the differences between the three?
什么是加入之间的区别bin
,bin/
,bin/*
和bin/**
在我的.gitignore文件?我一直在使用bin/
,但查看其他.gitignore 文件(在eclipse 文件中,双星和单星甚至像这样一起使用:tmp/**/*
这是怎么回事?)我看到前两种模式也被广泛使用。有人可以解释一下这三者之间的区别吗?
采纳答案by Siddhartha Reddy
bin
matches any files ordirectories named 'bin'.
bin
匹配任何名为“bin”的文件或目录。
bin/
matches any directoriesnamed 'bin', which in effect means all of its contents since Git doesn't track directories alone.
bin/
匹配任何名为“bin”的目录,这实际上意味着它的所有内容,因为 Git 不会单独跟踪目录。
bin/*
matches all files and directories directly in any bin/
. This prevents Git automatically finding any files in its subdirectories, but if, say a bin/foo
subdirectory is created, this rule will notmatch foo
's contents.
bin/*
直接匹配任何bin/
. 这可以防止 Git 自动在其子目录中查找任何文件,但是如果bin/foo
创建了一个子目录,则此规则将与的内容不匹配foo
。
bin/**
matches all files and directories in any bin/
directory and all of its subdirectories.
bin/**
匹配任何bin/
目录及其所有子目录中的所有文件和目录。
The word "any" is critical here since rules are not relative to the repository root and apply anywherein the filesystem tree. You must begin rules with a /
(or !/
to un-ignore) which means the repository's root, not the system's root, in order to match only what was intended.
“任何”一词在这里很重要,因为规则与存储库根无关,并且适用于文件系统树中的任何位置。您必须以/
(或!/
取消忽略)开始规则,这意味着存储库的根,而不是系统的根,以便仅匹配预期的内容。
WARNING:You should neveruse rules like dir/*
, /dir/**
, etc. alone unless you also un-ignore something that exists inside that directory. Omit the asterisk or you could permanently lose a lot of datafrom certain invocations of git gc
, git stash
and more.
警告:你应该从来没有使用类似的规则dir/*
,/dir/**
独自一人,等等,除非你也未忽略的东西,这个目录中存在。省略星号,否则您可能会因 的某些调用而永久丢失大量数据git gc
,git stash
等等。
I don't really know what tmp/**/*
is meant to do. I initially thought it could be used to match files in the sub-directories of tmp/
but not files directly present in tmp/
itself. But a simple test seems to suggest that this ignores all files in tmp/
.
我真的不知道要做什么tmp/**/*
。我最初认为它可以用于匹配子目录中的文件,tmp/
但不能用于匹配tmp/
本身直接存在的文件。但是一个简单的测试似乎表明这会忽略tmp/
.
回答by Simon Buchan
bin
and bin/
differ only in that the latter will only match a directory.
bin
而bin/
区别仅仅在于,后者将只匹配目录。
bin/**/*
is the same as bin/**
(apparently since 1.8.2, according to @VonC's answer).
bin/**/*
与bin/**
(根据@VonC 的回答,显然是从 1.8.2 开始)相同。
The tricky one, that I just spent an hour or so ripping my hair out over, is that bin/
and bin/**
are not quitethe same! Since the earlier ignores the directory as a whole, and the latter ignores each of the files within it, and git in nearly all cases doesn't care about directories, there is normally no difference. However, if you try to use !
to un-ignore a subpath, then you will find that git (ahem) ignoresit if you ignored the parent directory! (again, rather than the directory contents)
棘手的是,我只花了一个小时左右的时间把头发扯下来,这bin/
和bin/**
不完全一样!由于前者忽略整个目录,后者忽略其中的每个文件,并且 git 在几乎所有情况下都不关心目录,因此通常没有区别。但是,如果您尝试使用!
un-ignore 子路径,那么您会发现如果您忽略父目录,git (ahem) 会忽略它!(再次,而不是目录内容)
This is clearest by example, so for a newly init-ed repository set up so:
这通过示例最清楚,因此对于新初始化的存储库设置如下:
$ cat .gitignore
ignored-file
or-dir
dir-only/
!dir-only/cant-reinclude
dir-contents/**
!dir-contents/can-reinclude
$ mkdir or-dir dir-only dir-contents
$ touch file ignored-file or-dir/ignored-file dir-only/cant-reinclude dir-contents/can-reinclude
The following untracked files exist:
存在以下未跟踪文件:
$ git ls-files --other
.gitignore
dir-contents/can-reinclude
dir-only/cant-reinclude
file
ignored-file
or-dir/ignored-file
But you can see the following files are not ignored:
但是你可以看到以下文件没有被忽略:
$ git ls-files --other --exclude-standard
.gitignore
dir-contents/can-reinclude
file
And if you try to add, you get:
如果你尝试添加,你会得到:
$ git add dir-only/cant-reinclude
The following paths are ignored by one of your .gitignore files:
dir-only/cant-reinclude
Use -f if you really want to add them.
fatal: no files added
I consider this behavior a bug. (This is all on git version 1.8.4.msysgit.0
)
我认为这种行为是一个错误。(这一切都在git version 1.8.4.msysgit.0
)
回答by ThomasR
Note that, strictly speaking, git does not track directories, only files. It is hence not possible to add a directory, only its contents.
请注意,严格来说,git 不跟踪目录,只跟踪文件。因此无法添加目录,只能添加其内容。
In the context of .gitignore
however, git pretends to understand directories for the sole reason that
.gitignore
然而,在上下文中,git 假装理解目录的唯一原因是
It is not possible to re-include a file if a parent directory of that file is excluded.
https://git-scm.com/docs/gitignore#_pattern_format
如果排除了该文件的父目录,则无法重新包含该文件。
https://git-scm.com/docs/gitignore#_pattern_format
What does this mean for the exclude patterns? Let's go through them in detail:
这对排除模式意味着什么?让我们详细介绍一下它们:
bin
bin
This ignores
这忽略了
- files named
bin
. - the contents of folders named
bin
- 名为
bin
. - 名为的文件夹的内容
bin
You can whitelist ignored bin
files and folders by adding subsequent !
entries, but you cannot whitelist the contentsof folders named bin
您可以bin
通过添加后续!
条目将忽略的文件和文件夹列入白名单,但不能将名为的文件夹的内容列入白名单bin
bin
!bin/file_in_bin # has no effect, since bin/ is blacklisted!
!bin/* # has no effect, since bin/ is blacklisted!
!file_in_bin # has no effect, since bin/ is blacklisted!
!bin # this works
bin/
bin/
Same as above, except it does not match filesnamed bin
. Adding a trailing /
tells git to match directories only.
和上面一样,只是它不符合文件命名bin
。添加尾随/
告诉 git 仅匹配目录。
bin/*
bin/*
This ignores
这忽略了
- filescontained in a folder named
bin
- contents of direct subfolders of folders named
bin
- 文件包含一个命名的文件夹中
bin
- 名为的文件夹的直接子文件夹的内容
bin
bin/* # blacklists bin/file_in_bin and bin/subfolder/
!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted!
!bin # whitelists files named bin/bin, since bin/ itself is not blacklisted
!bin/ # has no effect, since bin/ itself is not blacklisted
!bin/file_in_bin # works since bin/ itself is not blacklisted
!file_in_bin # works too
!bin/subfolder # works (so implicitly whitelists bin/subfolder/file_in_sub)
!bin/subfolder/ # works just as well
!bin/* # works for file_in_bin and subfolder/
bin/**
bin/**
This ignores
这忽略了
- contents of
bin
- contents of subfolders (any level of nesting) within
bin
- 的内容
bin
- 子文件夹的内容(任何嵌套级别)
bin
bin/** # blacklists bin/file_in_bin and
# bin/subfolder/ and bin/subfolder/file_in_sub and
# bin/subfolder/2/ and bin/subfolder/2/file_in_sub_2
!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/ # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/file_in_sub_2 # has no effect, since bin/subfolder is blacklisted
!bin/subfolder # works only in combinations with other whitelist entries,
# since all contents of subfolder are blacklisted (1)
!bin/file_in_bin # works since bin itself is not blacklisted
!bin/* # works for file_in_bin and subfolder; see (1)
回答by Joe Phillips
I just made a new repo and tried some things. Here are my results:
我刚刚做了一个新的回购并尝试了一些东西。这是我的结果:
NEW RESULTS
新结果
git version 2.10.1.windows.1
git 版本 2.10.1.windows.1
- Initialize nearly-empty repo. Only the README file
- Populate the
bin
directory several layers deepbin.txt
Test.txt
bin/a/b/bin.txt
bin/a/b/Test.txt
bin/a/bin/bin.txt
bin/a/bin/Test.txt
bin/a/bin.txt
bin/a/Test.txt
bin/bin.txt
bin/Test.txt
- Add
bin
to gitignore: Results- Everything beneath the
bin
directory (and deeper) is now ignored - Root level is not ignored (/bin.txt and /Test.txt still show)
- Everything beneath the
- Edit
bin
tobin/
in the gitignore: Results- No change
- Edit
bin/
tobin/*
- No change
- Edit
bin/*
tobin/**
- No change
- Edit
bin/**
tobin/**/
bin/bin.txt
andbin/Test.txt
are no longer ignored
- Edit
bin/**/
tobin/**/*
bin/bin.txt
andbin/Test.txt
are back to being ignored
- 初始化几乎为空的 repo。只有 README 文件
- 将
bin
目录填充几层深bin.txt
Test.txt
bin/a/b/bin.txt
bin/a/b/Test.txt
bin/a/bin/bin.txt
bin/a/bin/Test.txt
bin/a/bin.txt
bin/a/Test.txt
bin/bin.txt
bin/Test.txt
- 添加
bin
到 gitignore:结果- 在下面的一切
bin
目录(和深)现在被忽略 - 根级别不会被忽略(/bin.txt 和 /Test.txt 仍然显示)
- 在下面的一切
- 编辑
bin
要bin/
在gitignore:结果- 没变
- 编辑
bin/
为bin/*
- 没变
- 编辑
bin/*
为bin/**
- 没变
- 编辑
bin/**
为bin/**/
bin/bin.txt
并bin/Test.txt
不再被忽略
- 编辑
bin/**/
为bin/**/*
bin/bin.txt
并bin/Test.txt
重新被忽视
OLD RESULTS
旧结果
git version: 2.7.0.windows.1
git 版本:2.7.0.windows.1
- Initialize nearly-empty repo. Only the README file
- Populate the
bin
directory several layers deepbin/a/b/Test.txt
bin/a/bin/Test.txt
bin/a/Test.txt
bin/Test.txt
- Add
bin
to gitignore: Results- Everything beneath the
bin
directory (and deeper) is now ignored
- Everything beneath the
- Edit
bin
tobin/
in the gitignore: Results- Everything beneath the
bin
directory (and deeper) is still ignored (no change)
- Everything beneath the
- Edit
bin/
tobin/*
- Everything beneath the
bin
directory (and deeper) is still ignored (no change)
- Everything beneath the
- Edit
bin/*
tobin/**
- Everything beneath the
bin
directory (and deeper) is still ignored (no change)
- Everything beneath the
- Edit
bin/**
tobin/**/
bin/Test.txt
is no longer ignored
- Edit
bin/**/
tobin/**/*
- Everything beneath the
bin
directory (and deeper) is ignored again
- Everything beneath the
- 初始化几乎为空的 repo。只有 README 文件
- 将
bin
目录填充几层深bin/a/b/Test.txt
bin/a/bin/Test.txt
bin/a/Test.txt
bin/Test.txt
- 添加
bin
到 gitignore:结果- 在下面的一切
bin
目录(和深)现在被忽略
- 在下面的一切
- 编辑
bin
要bin/
在gitignore:结果- 在下面的一切
bin
目录(和深)是被忽略(没有变化)
- 在下面的一切
- 编辑
bin/
为bin/*
- 在下面的一切
bin
目录(和深)是被忽略(没有变化)
- 在下面的一切
- 编辑
bin/*
为bin/**
- 在下面的一切
bin
目录(和深)是被忽略(没有变化)
- 在下面的一切
- 编辑
bin/**
为bin/**/
bin/Test.txt
不再被忽视
- 编辑
bin/**/
为bin/**/*
- 在下面的一切
bin
目录(和深)再次忽略
- 在下面的一切
回答by VonC
Note that the '**
', when combined with a sub-directory(**/bar
), must have changed from its default behavior, since the release note for git1.8.2now mentions:
请注意**
,当与子目录( **/bar
)结合使用时, ' '肯定已经改变了其默认行为,因为git1.8.2的发行说明现在提到:
The patterns in
.gitignore
and.gitattributes
files can have**/
, as a pattern that matches 0 or more levels of subdirectory.E.g. "
foo/**/bar
" matches "bar
" in "foo
" itself or in a subdirectory of "foo
".
.gitignore
和.gitattributes
文件中的模式可以有**/
, 作为匹配 0 个或多个子目录级别的模式。例如,“
foo/**/bar
”匹配“bar
”foo
本身或“foo
”子目录中的“ ”。
The rule to remember (and which help understand the difference of intent behind those syntax) is:
要记住的规则(有助于理解这些语法背后的意图差异)是:
It is not possible to re-include a file if a parent directory of that file is excluded.
Typically, if you want to exclude files from a subfolder of an ignore folder f, you would do:
通常,如果您想从忽略文件夹 f 的子文件夹中排除文件,您可以执行以下操作:
f/**
!f/**/
!f/a/sub/folder/someFile.txt
That is:
那是:
- If the first rule was
f/
, the folderf/
would be ignored and rules below regardingf
would not matter. f/**
achieve the same asf/
, but ignore all sub-elements(files and subfolders).
That gives you the opportunity to whitelist (exclude from gitignore) the subfolders:!f/**/
.- Since all
f
subfolders are notignored, you can add a rule to exclude a file (!f/a/sub/folder/someFile.txt
)
- 如果第一条规则是
f/
,则该文件夹f/
将被忽略,并且下面有关的规则f
无关紧要。 f/**
实现与 相同f/
,但忽略所有子元素(文件和子文件夹)。
这使您有机会将子文件夹列入白名单(从 gitignore 中排除):!f/**/
.- 由于不会忽略所有
f
子文件夹,因此您可以添加规则以排除文件 ( )!f/a/sub/folder/someFile.txt
回答by user1431317
There's another difference between bin/*
and bin/
.
bin/*
和之间还有另一个区别bin/
。
bin/
matches foo/bin/test.txt
(as expected), but bin/*
does not, which seems strange, but it's documented: https://git-scm.com/docs/gitignore
bin/
匹配foo/bin/test.txt
(如预期),但bin/*
不匹配,这看起来很奇怪,但已记录在案:https: //git-scm.com/docs/gitignore
"Documentation/*.html" matches "Documentation/git.html" but not "Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html".
“Documentation/*.html”匹配“Documentation/git.html”但不匹配“Documentation/ppc/ppc.html”或“tools/perf/Documentation/perf.html”。
The reason for this appears to be these rules:
其原因似乎是这些规则:
If the pattern ends with a slash, it is removed for the purpose of the following description …
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 …
Otherwise, Git treats the pattern as a shell glob suitable for consumption by fnmatch(3) with the FNM_PATHNAME flag …
如果模式以斜杠结尾,则出于以下描述的目的将其删除……
如果模式不包含斜杠 /,Git 会将其视为 shell glob 模式并检查与相对于 .gitignore 文件位置的路径名的匹配项……
否则,Git 将模式视为适合 fnmatch(3) 使用 FNM_PATHNAME 标志的 shell glob……
So if the pattern ends with a slash, the slash is removed and it's treated as a shell glob pattern, in which case bin
matches foo/bin/test.txt
.
If it ends with /*
, the slash isn't removed and it's passed to fnmatch, which doesn't match in subdirectories.
因此,如果模式以斜杠结尾,则将删除斜杠并将其视为 shell glob 模式,在这种情况下bin
匹配foo/bin/test.txt
. 如果以 结尾/*
,则不会删除斜杠,而是将其传递给 fnmatch,它在子目录中不匹配。
However, the same is not true for foo/bin/
and foo/bin/*
, because even after removing the trailing slash from foo/bin/
, it still contains a slash, so it's treated as an fnmatch pattern, not a glob. I.e. it will not match bar/foo/bin/test.txt
但是,foo/bin/
and不是这样foo/bin/*
,因为即使从 中删除了尾部斜杠foo/bin/
,它仍然包含一个斜杠,因此它被视为 fnmatch 模式,而不是 glob。即它不会匹配bar/foo/bin/test.txt