.gitignore:/foo 和 /foo/ 之间的区别

5

foo//foo/.gitignore文件中有什么不同吗?我已经在git-doc中阅读过,但没有找到答案。这两者是否相同?

2个回答

5

/foofoo之间是有区别的。

要理解这个区别,可以想一想目录(或者如果你更喜欢这个词,文件夹)以及它们可能包含嵌套的子目录(子文件夹):

foo/a/file1
foo/b/file2
foo/file3
quux/foo/file4

在这里,顶层目录foo包含两个子目录ab以及一个文件,并且子目录中分别包含一个文件。顶级目录quux包含一个子目录foo,其中包含一个文件。

如果您的.gitignore列出了foo

如果告诉Git忽略foo,Git就不必查看foo/afoo/bfoo/file3,因为没有查看foo,所以Git也不会查看foo/afoo/b,也不会找到foo/a/file1foo/b/file2
与此同时,没有任何内容告诉Git跳过quux,因此Git将查看quux并找到foo。如果告诉Git忽略foo,Git就不必查看quux/foo,因此不会找到quux/foo/file4

如果您的.gitignore列出了/foo

但是,如果告诉Git忽略/foo而不是foo,当Git在quux中找到foo时,它不会匹配/foo,因为/foo的意思是仅忽略顶级的foo。所以Git会查看quux/foo,因此会找到quux/foo/file4

后缀斜杠

正如Void Raider回答的那样,在.gitignore中写入foo/告诉Git它应该匹配(因此不查看)目录foo,但不应该匹配(因此会抱怨-见下文)名为foo的普通文件。这里,前导斜杠仍然很重要:它告诉Git是否将其应用于所有名为foo的内容,还是只适用于顶层的那些东西。

更多细节,因为细节很重要

以上所有内容都是描述了只有一个 .gitignore 文件存储在你的工作树的顶层,但你可以在每个目录中存储一个 .gitignore 文件。例如,如果你有一个名为 quux 的目录,你可以创建 quux/.gitignore 文件。在顶层的 .gitignore 中,你可以列出像 quux/foo 这样的名称,或者你可以在 quux/.gitignore 中列出 foo。那么这些各自是做什么的呢?
首先,让我们定义一些术语:
- Unix 风格的路径名通常称为“绝对路径”,如果它们以 / 开头,例如 /a/b/c,或者称为“相对路径”,如果它们不以 / 开头,例如 a/b/c。绝对路径告诉操作系统从主机的目录树顶部开始,而相对路径告诉操作系统从“当前目录”开始。 - Unix 风格的 shell 支持称为“globbing”或“glob”的路径名操作。例如,* 匹配任意数量(包括零)的任何字符,因此像 a*c 这样的名称匹配 acabcabbbcaxyzc 等等。 - 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 显示了正在处理不同或提交前暂存的文件。
第二个比较将索引中的内容与您的工作树中的内容进行比较。在这里 不同 的任何内容,称为未暂存或对于某些文件,称为未跟踪。其中一些未跟踪文件将是您不想提交的文件,并且您不希望Git干扰您的文件。
一个“未被跟踪的文件”简单地定义为“根本不在索引中的路径名”。 如果同样的路径名存在于工作树中,则该文件未被跟踪。 Git会对此发出警告。 在.gitignore文件中列出该路径名将告诉Git:“闭嘴,这个文件应该是未跟踪的。”但是如果它被“跟踪”,也就是说文件已经在索引中,Git不会检查.gitignore文件中的名称;它只会假设该文件应该被提交。

非常有用的一点是,如果一个文件已经在索引中,那么git就不会检查.gitignore。这解释了为什么git允许我提交一些本应该根据.gitignore忽略的文件。 - undefined

0
基本上,/foo 会匹配文件或目录,/foo/ 只匹配目录,而 /foo/* 则匹配 foo 内的目录和文件。希望这能帮到你!
编辑:另外,/foo/foo/ 是相同的。

3
/foo/foo/ 不是 同一个!前者会忽略任何文件或目录,而后者只会忽略目录。此外,您还忘记了 foo//foo/ 之间的区别——区别在于 foo/ 匹配任何子目录,而 /foo/ 只匹配 .gitignore 所在的同一目录。 - phd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接