当我与设置进行比较时,我发现/*
和*
有不同的方法:
*
!/init.el
!/README.md
!.gitignore
!/lib/
VS
/*
!/init.el
!/README.md
!.gitignore
!/lib/
前者不跟踪/lib/
,但后者跟踪它。
如何处理*
和/*
?
更新
我认为这个问题与另一个问题并不完全相同。因为他专注于dir/**
和dir/*
,但这个重点是/*
和*
。
答案 0 :(得分:3)
第一个版本忽略除明确列出的文件之外的所有文件。 lib
被忽略,因为它不包含可跟踪文件。 Git不跟踪文件夹,因此看起来空的目录似乎被忽略了。
第二个版本忽略除明确列出的所有根级别文件和目录。 不会忽略根目录中可跟踪且不的任何内容。 lib
已明确列出,因此不会被忽略。它包含的任何文件都不在根级别,因此它们也不会被忽略。
答案 1 :(得分:2)
答案有点复杂,因为Git的扫描算法很棘手,但归结为*
匹配lib/custom-file.el
但/*
不匹配。
作为一般规则,在glob模式中,*
不会“交叉”路径名称分隔符/
- es。因此A*B
匹配ANameThatEndsInB
但不匹配ADirectory/WithAFileB
。
将/
置于glob模式中需要/
之前的事物命名目录,/
之后的事物在目录中出现:A*/*B
匹配ADirectory/WithAFileB
。名称组件ADirectory
和WithAFileB
分别与glob组件A*
和*B
匹配。
/
中的结尾结尾,与*/
中的仅匹配目录。一个以/
开头在Git中具有另一个特殊含义(但请注意,例如,.gitignore
条目/foo/bar/
由两个组成部分组成:/foo/
然后bar/
; bar/
部分不以斜杠开头)。特别是,如果模式以/
开头,则它仅适用于该Git目录顶层的文件。如果那是顶级.gitignore
,那么这意味着工作树本身的根。
现在,就像在Mad Physicist's answer中一样,如果Git在目录中没有跟踪的文件,Git就不必读取该目录了。如果Git还没有因某些其他原因扫描该目录,那么匹配目录名称的忽略模式将使Git 跳过扫描目录。所以一般情况下,如果你的.gitignore
中有*
,那么任何目录都会被完全跳过,只要Git没有必要查看其他目录原因。因此*
中的.gitignore
会忽略所有目录。但是,Git忽略规则说每当Git持有文件或目录名并检查.gitignore
个文件时,它应该通读整个文件并找到 all 匹配,包括前面带!
的匹配。这意味着,例如:
*
!*/
会告诉Git忽略所有内容(包括目录),但是通过说不忽略*/
目录来覆盖它。但*
将继续忽略所有文件。
如果您阅读:
/*
!/*/
您将忽略此目录中的所有文件(包含.gitignore
的文件),但让Git扫描其所有子目录。任何子目录(例如foo/name
)内的所有内容都将无法匹配这些glob模式中的任何一个,因为foo/name
部分有斜杠而*
无法跨越它。