foo/
和/foo/
在.gitignore
文件中有什么不同吗?我已经在git-doc中阅读过,但没有找到答案。这两者是否相同?
/foo和foo之间是有区别的。
要理解这个区别,可以想一想目录(或者如果你更喜欢这个词,文件夹)以及它们可能包含嵌套的子目录(子文件夹):
foo/a/file1
foo/b/file2
foo/file3
quux/foo/file4
foo
包含两个子目录a
和b
以及一个文件,并且子目录中分别包含一个文件。顶级目录quux
包含一个子目录foo
,其中包含一个文件。
.gitignore
列出了foo
foo
,Git就不必查看foo/a
、foo/b
和foo/file3
,因为没有查看foo
,所以Git也不会查看foo/a
或foo/b
,也不会找到foo/a/file1
或foo/b/file2
。quux
,因此Git将查看quux
并找到foo
。如果告诉Git忽略foo
,Git就不必查看quux/foo
,因此不会找到quux/foo/file4
。
.gitignore
列出了/foo
/foo
而不是foo
,当Git在quux
中找到foo
时,它不会匹配/foo
,因为/foo
的意思是仅忽略顶级的foo
。所以Git会查看quux/foo
,因此会找到quux/foo/file4
。
.gitignore
中写入foo/
告诉Git它应该匹配(因此不查看)目录foo
,但不应该匹配(因此会抱怨-见下文)名为foo
的普通文件。这里,前导斜杠仍然很重要:它告诉Git是否将其应用于所有名为foo
的内容,还是只适用于顶层的那些东西。
.gitignore
文件存储在你的工作树的顶层,但你可以在每个目录中存储一个 .gitignore
文件。例如,如果你有一个名为 quux
的目录,你可以创建 quux/.gitignore
文件。在顶层的 .gitignore
中,你可以列出像 quux/foo
这样的名称,或者你可以在 quux/.gitignore
中列出 foo
。那么这些各自是做什么的呢?/
开头,例如 /a/b/c
,或者称为“相对路径”,如果它们不以 /
开头,例如 a/b/c
。绝对路径告诉操作系统从主机的目录树顶部开始,而相对路径告诉操作系统从“当前目录”开始。
- Unix 风格的 shell 支持称为“globbing”或“glob”的路径名操作。例如,*
匹配任意数量(包括零)的任何字符,因此像 a*c
这样的名称匹配 ac
、abc
、abbbc
、axyzc
等等。
- Git 支持(在多个位置,包括 .gitattributes
和命令行选项中)路径名“模式”,Git 称之为“pathspecs”。Git 中的不同功能支持不同类型的 pathspecs。忽略文件特别实现了 glob 模式。.gitignore
文件中,任何绝对路径总是指当前目录。因此,如果存在 quux/.gitignore
文件,并且其中包含 /foo
,那么它匹配名为 quux/foo
的文件或目录。你可以将其放入顶层的 .gitignore
文件中作为 /quux/foo
。.gitignore
文件中,任何包含嵌入式 /
(不在模式末尾)的路径名也被视为绝对路径!这意味着将 quux/foo
放入顶层 .gitignore
中与将 /quux/foo
放入顶层 .gitignore
是相同的!foo
放入 quux/.gitignore
中,意味着 Git 会忽略 quux/sub/foo
;而把 quux/foo
放入顶级的 .gitignore
中,则表示 Git 不会忽略 quux/sub/foo
,这是因为处理嵌套斜杠路径名的特殊性质使其像绝对路径一样。.gitignore
文件都无法忽略它。git ls-files --stage
命令可以查看当前在索引中的所有内容。请注意,这将在大型版本库中打印出大量文件名!通常情况下,您不会直接查看索引:它就像太阳一样,过于庞大。更好的方式是将索引与其他内容进行比较。这就是 git status
的作用,并且这就是 .gitignore
文件真正发挥作用的地方。git status
命令时,Git 进行了两个比较。第一个比较将当前或 HEAD
提交与索引进行比较。在这里 不同 的任何内容,称为在提交前暂存的内容。这是因为 git commit
将使用当前索引中的内容来创建新快照。我们通常关注的不是将在新快照中存在的每个文件,而是与当前快照相比在新快照中将会有所不同的那些文件。因此,git status
显示了正在处理不同或提交前暂存的文件。.gitignore
文件中列出该路径名将告诉Git:“闭嘴,这个文件应该是未跟踪的。”但是如果它被“跟踪”,也就是说文件已经在索引中,Git不会检查.gitignore
文件中的名称;它只会假设该文件应该被提交。/foo
会匹配文件或目录,/foo/
只匹配目录,而 /foo/*
则匹配 foo 内的目录和文件。希望这能帮到你!/foo
和 /foo/
是相同的。/foo
和 /foo/
不是 同一个!前者会忽略任何文件或目录,而后者只会忽略目录。此外,您还忘记了 foo/
和 /foo/
之间的区别——区别在于 foo/
匹配任何子目录,而 /foo/
只匹配 .gitignore
所在的同一目录。 - phd