这是Where is gitignore recursive behavior specified?的确切问题,因为我认为它的公认答案不能解释git文档中指定gitignore模式的递归行为的内容。
请考虑以下情形。存储库的结构是
.gitignore
a
|
-- f
(也就是说,在存储库的根目录中有一个.gitignore
文件和一个名为a
的文件夹,在a
中有一个名为f
的文件)
存储库根目录中的.gitignore
文件包含f
作为唯一模式。
现在,如果我们要阅读gitignore documentation,我们将发现以下paragrah(强调我的意思):
如果该模式不包含斜杠/,则Git会将其视为Shell Glob模式,并检查相对于.gitignore文件位置的路径名是否匹配(相对于顶层(如果不是来自.gitignore文件的话)。
从上面引用的段落中我了解到,git
检查文件f
是否应被忽略时,它将尝试相对于.gitignore的位置匹配其“ 路径名”文件”。因此,它将尝试将模式f
与a/f
进行匹配,该模式不应匹配。
我的理解不正确吗?谢谢。
答案 0 :(得分:3)
您误读了粗体的短语(我承认这很容易做到-Git文档通常令人不满意。)
“相对于.gitignore文件的位置”这句话是尝试传达的这个想法:
.gitignore
bar
dir/
dir/.gitignore
dir/bar
dir/hello
foo
hello
假设.gitignore
由行hello
组成,而dir/.gitignore
由行bar
组成。 两个目录中的文件hello
被忽略,因为hello
在顶层被忽略,而顶层目录中的文件bar
在 被忽略,因为bar
忽略了dir/.gitignore
,这仅影响dir
中的文件和dir
的子目录。
关于.gitignore
条目中的模式中的斜杠的内容特别棘手。该文档说,(一个)尾部斜杠被临时删除以做出决定:该条目是否包含斜杠?然后将其放回去。我认为用这种更好的措辞来表达这种说法(不是说Git这样做的话)是这样说的:“且仅当条目包含不是条目中最后一个字符的斜杠时,该条目才是 rooted 。”这种“生根”思路意味着完整的(相对于.gitignore
位置)路径名必须匹配。否则,该模式将在该目录及其所有子目录中都匹配,这与您在此处看到的问题大致相同。
请记住,.gitignore
并不是真的忽略。这通常意味着不要抱怨未跟踪的文件。
仅当文件位于Git的索引中时,文件才会被跟踪。索引的内容会随着时间的变化而变化-它们最初是“您刚刚检出的提交中的内容”,但是您可以用git add
替换其中的文件,或将新文件放入其中,然后您可以使用git rm
(或为此,使用git add
!)从文件中删除文件。如果跟踪文件 (即,如果该文件的名称现在在索引 中),则该文件名与任何.gitignore
条目的任何匹配都将完全不相关。
仅跟踪文件。因此,目录的.gitignore
条目很奇怪。目录将永远不会被跟踪。相应地,.gitignore
中的目录名称的效果尤其怪异而棘手。
忽略Git中整个目录的内部,面向性能的目标并不是“使用户更容易表达”,而是“使Git真正快速地运行,就像赛车一样”。在悬崖上以700英里/小时的速度行驶!”
Git较慢的部分之一是枚举,一次枚举一个文件,每个文件和子目录以及所有子目录的文件 在某个目录中,因为Git必须不断询问操作系统,一次一个文件,每个文件 about (进行lstat
系统调用)。 Git员工观察到,如果您可以某种方式告诉Git:甚至不查看 vendor
目录,则可以跳过成千上万个SDK文件从而使git status
变得非常快。
为此,如果您列出vendor
或vendor/
(或/vendor/
以将模式植根到保存.gitignore
文件的目录中),则和< / em> Git的索引中没有 no 名为vendor/anything
的文件, then –只有这样,Git才能跳过vendor
目录,然后不必枚举数千个SDK文件。
另一方面,如果您列出vendor/*
或/vendor/*
,则两者含义相同,因为它们都包含一个/
而不是最后一个/
, Git 必须打开并读取vendor
目录。无论所有一万个文件(和/或子目录)是否都在该目录的顶层,Git都可以跳过它们(毕竟它们与vendor/*
匹配),但是首先必须枚举至少位于vendor
目录的顶层。通过此枚举过程,您可以取消-忽略任何特定的子目录或文件,例如vendor/REMEMBER_WHICH_VERSION_WE_GOT
(尽管最好记住 outside 供应商子树)。
(请注意,一旦某个目录中存在跟踪文件,即使名义上忽略该目录,Git也必须在该目录中查找。因此,此make-the-race-car-go-fast-even-if-有一个悬崖附近的技巧仅适用于其中没有跟踪文件的情况,即,在这种颇为扭曲的类比中,强制Git跟踪文件可确保也没有悬崖。)