git是否为gitignore模式指定递归行为?

时间:2019-01-12 13:57:34

标签: git gitignore

这是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的位置匹配其“ 路径名”文件”。因此,它将尝试将模式fa/f进行匹配,该模式不应匹配。

我的理解不正确吗?谢谢。

1 个答案:

答案 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的子目录。

  1. 关于.gitignore条目中的模式中的斜杠的内容特别棘手。该文档说,(一个)尾部斜杠被临时删除以做出决定:该条目是否包含斜杠?然后将其放回去。我认为用这种更好的措辞来表达这种说法(不是说Git这样做的话)是这样说的:“且仅当条目包含不是条目中最后一个字符的斜杠时,该条目才是 rooted 。”这种“生根”思路意味着完整的(相对于.gitignore位置)路径名必须匹配。否则,该模式将在该目录及其所有子目录中都匹配,这与您在此处看到的问题大致相同。

  2. 请记住,.gitignore并不是真的忽略。这通常意味着不要抱怨未跟踪的文件。

    仅当文件位于Git的索引中时,文件才会被跟踪。索引的内容会随着时间的变化而变化-它们最初是“您刚刚检出的提交中的内容”,但是您可以用git add替换其中的文件,或将新文件放入其中,然后您可以使用git rm(或为此,使用git add!)从文件中删除文件。如果跟踪文件 (即,如果该文件的名称现在在索引 中),则该文件名与任何.gitignore条目的任何匹配都将完全不相关。

  3. 仅跟踪文件。因此,目录的.gitignore条目很奇怪。目录将永远不会被跟踪。相应地,.gitignore中的目录名称的效果尤其怪异而棘手。

    忽略Git中整个目录的内部,面向性能的目标并不是“使用户更容易表达”,而是“使Git真正快速地运行,就像赛车一样”。在悬崖上以700英里/小时的速度行驶!”

    Git较慢的部分之一是枚举,一次枚举一个文件,每个文件和子目录以及所有子目录的文件 在某个目录中,因为Git必须不断询问操作系统,一次一个文件,每个文件 about (进行lstat系统调用)。 Git员工观察到,如果您可以某种方式告诉Git:甚至不查看 vendor目录,则可以跳过成千上万个SDK文件从而使git status变得非常快。

    为此,如果您列出vendorvendor/(或/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跟踪文件可确保也没有悬崖。)