在我的.gitignore文件中添加bin
,bin/
,bin/*
和bin/**
之间的区别是什么?我一直在使用bin/
,但是看other .gitignore files(在eclipse file中,双星和单星甚至一起使用:tmp/**/*
什么是那个?)我看到前两个模式也被广泛使用。有人可以解释三者之间的差异吗?
答案 0 :(得分:77)
bin
匹配任何名为'bin'的或目录。
bin/
匹配任何名为'bin'的目录,这实际上意味着它的所有内容,因为Git不会单独跟踪目录。
bin/*
直接匹配任何bin/
中的所有文件和目录。这可以防止Git自动查找其子目录中的任何文件,但如果创建了bin/foo
子目录,则此规则不匹配foo
的内容。
bin/**
匹配任何bin/
目录及其所有子目录中的所有文件和目录。
“any”这个词在这里至关重要,因为规则与存储库根目录无关,并且在文件系统树中的任何地方。您必须使用/
(或!/
取消忽略)开始规则,这意味着存储库的根,而不是系统的根,以便仅匹配预期的内容。
警告:永远不会单独使用dir/*
,/dir/**
等规则,除非您也忽略了某些内容存在于该目录中。从git gc
,git stash
等的某些调用中省略星号或you could permanently lose a lot of data。
我真的不知道tmp/**/*
的意图。我最初认为它可以用于匹配tmp/
子目录中的文件,但不能用于tmp/
本身直接存在的文件。但是一个简单的测试似乎表明这会忽略tmp/
中的所有文件。
答案 1 :(得分:42)
bin
和bin/
的区别仅在于后者只匹配目录。
bin/**/*
与bin/**
相同(显然自1.8.2以来,根据@ VonC的回答)。
狡猾的一个,我花了一个小时左右的时间将头发翻过来,bin/
和bin/**
相当相同!由于早期忽略了整个目录,而后者忽略了其中的每个文件,并且git几乎在所有情况下都不关心目录,因此通常没有区别。但是,如果您尝试使用!
取消忽略子路径,那么如果忽略父目录,您会发现git(ahem)忽略它! (再次,而不是目录内容)
这是最明显的示例,因此对于新建立的存储库设置如此:
$ 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
存在以下未跟踪的文件:
$ git ls-files --other
.gitignore
dir-contents/can-reinclude
dir-only/cant-reinclude
file
ignored-file
or-dir/ignored-file
但您可以看到以下文件不会被忽略:
$ git ls-files --other --exclude-standard
.gitignore
dir-contents/can-reinclude
file
如果你试图添加,你会得到:
$ 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
我认为这种行为是个错误。 (全部在git version 1.8.4.msysgit.0
)
答案 2 :(得分:18)
请注意,严格来说,git不会跟踪目录,只跟踪文件。因此无法添加目录,只能添加内容。
然而,在.gitignore
的上下文中,git假装理解目录的唯一原因是
如果排除该文件的父目录,则无法重新包含文件 https://git-scm.com/docs/gitignore#_pattern_format
这对排除模式意味着什么?让我们详细介绍一下:
bin
忽略
bin
的文件。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
的文件不匹配。添加尾随/
告诉git仅匹配目录。
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
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)
答案 3 :(得分:9)
我刚刚制作了一个新的回购并试了一些东西。以下是我的结果:
git version 2.10.1.windows.1
.clear()
目录填充多个深层
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
添加到gitignore:结果
bin
目录(及更深层)下的所有内容bin
到bin
:结果
bin/
修改为bin/
bin/*
修改为bin/*
bin/**
修改为bin/**
bin/**/
和bin/bin.txt
不再被忽略bin/Test.txt
修改为bin/**/
bin/**/*
和bin/bin.txt
又回到了被忽略git版本:2.7.0.windows.1
bin/Test.txt
目录填充多个深层
bin
bin/a/b/Test.txt
bin/a/bin/Test.txt
bin/a/Test.txt
bin/Test.txt
添加到gitignore:结果
bin
目录(及更深层)下的所有内容bin
到bin
:结果
bin/
目录(及更深层)下的所有内容仍然被忽略(无变化)bin
修改为bin/
bin/*
目录(及更深层)下的所有内容仍然被忽略(无变化)bin
修改为bin/*
bin/**
目录(及更深层)下的所有内容仍然被忽略(无变化)bin
修改为bin/**
bin/**/
不再被忽视bin/Test.txt
修改为bin/**/
bin/**/*
目录(及更深层)下的所有内容答案 4 :(得分:8)
请注意,'**
',与子目录(**/bar
)结合使用时,必须更改其默认行为,因为{{3}现在提到:
.gitignore
和.gitattributes
文件中的模式可以有**/
,作为匹配0或更多级别子目录的模式。E.g。 “
foo/**/bar
”与“bar
”本身或“foo
”的子目录中的“foo
”匹配。
要记住的规则(以及帮助理解这些语法背后的意图差异)是:
通常,如果要从忽略文件夹f的子文件夹中排除文件,您可以这样做:
f/**
!f/**/
!f/a/sub/folder/someFile.txt
那是:
f/
,则会忽略文件夹f/
,以下有关f
的规则无关紧要。 f/**
与f/
实现相同,但忽略所有子元素(文件和子文件夹)。!f/**/
。 f
个子文件夹未被忽略,您可以添加规则以排除文件(!f/a/sub/folder/someFile.txt
)答案 5 :(得分:0)
bin/*
和bin/
之间存在另一个区别。
bin/
匹配foo/bin/test.txt
(正如预期的那样),但bin/*
不匹配,这似乎很奇怪,但记录在案:https://git-scm.com/docs/gitignore
“Documentation / * .html”匹配“Documentation / git.html”但不匹配 “Documentation / ppc / ppc.html”或“tools / perf / Documentation / perf.html”。
原因似乎是这些规则:
如果图案以斜线结尾,则会出于以下说明的目的将其删除...
如果模式不包含斜杠/,Git会将其视为shell glob模式,并检查相对于.gitignore文件位置的路径名匹配...
否则,Git将模式视为适合fnmatch(3)使用FNM_PATHNAME标志消耗的shell glob ...
因此,如果模式以斜杠结尾,则删除斜杠并将其视为shell glob模式,在这种情况下bin
匹配foo/bin/test.txt
。
如果它以/*
结尾,则不会删除斜杠并将其传递给fnmatch,后者在子目录中不匹配。
但是,对于foo/bin/
和foo/bin/*
,情况并非如此,因为即使从foo/bin/
中删除尾部斜杠,它仍然包含斜杠,因此它被视为fnmatch模式不是一个水珠。即它不匹配bar/foo/bin/test.txt