我试图更清楚地理解
.gitignore
语法,特别是 https://github.com/github/gitignore gitignore。
我看到前导斜杠用于仅匹配相对于
.gitignore
文件位置的路径名(来自 http://git-scm.com/docs/gitignore):
前导斜杠与路径名的开头匹配。例如,“/*.c”匹配“cat-file.c”,但不匹配“mozilla-sha1/sha1.c”。
但是当我删除前导斜杠时会发生什么?据我了解,有两种情况:
dir/
将匹配 <root>/dir
、<root>/a/dir
、<root>/a/b/c/.../dir
等,其中 <root>
是 .gitignore
文件的位置。.gitignore
文件位置的路径名匹配。这些是我用来检查此行为的示例:
# Directory structure:
<root>
├─ dir/
│ └─ test
├─ src/
│ ├─ dir/
│ │ └─ test
test file is there only because Git does not track empty directories.
第一次测试:
# .gitignore
dir/
# git status
nothing to commit
所以 Git 会忽略这两个
dir
目录。这与第 1 种情况一致:该模式没有斜杠(尾随斜杠除外),因此 Git 正在监视整个目录树,忽略与该模式匹配的所有内容。
第二次测试:
# .gitignore
/dir/
# git status
Untracked files:
src/
这里,由于模式中的前导斜杠,Git 仅忽略根目录正下方的
dir
目录。
第三次测试:
# .gitignore
dir/*
# git status
Untracked files:
src/
这与情况 2 一致:该模式内部有一些斜杠,因此它被视为从根目录开始的路径名。
现在是真正问题的时候了。让我们考虑一下这个 gitignore 文件:例如,当他们忽略目录
downloader/
时,他们实际上不是忽略了整个目录树中找到的每个 downloader
目录吗?自从我之前看到 Git 的工作原理以来,这就是我所迫不及待的想法。
因此,如果我碰巧有一个自定义模块,其中包含
downloader
目录,它会像 Magento 根目录中的常规模块一样被意外忽略吗?这是一个有点反问的问题,因为它实际上已经发生在我身上,产生了一个很难发现的错误。
因此,在 Magento
.gitignore
文件中(顺便说一句,我仅作为示例提及),许多模式都包含斜杠,因此它们与从根开始的路径名正确匹配,但有几种情况,比如 downloader/
或 errors/
,如果我没记错的话,有潜在危险,应该改为 /downloader/
和 /errors/
。
作为一个更普遍的问题,当我想选择显式从根开始的路径名而不是将其用于包含斜杠的模式时,我是否应该始终对不包含斜杠的模式(尾随斜杠除外)使用前导斜杠,或者应该为了清晰起见,我总是使用前导斜杠?对此你有何感想?
感谢您的阅读,对这么长的帖子表示歉意。
只是想总结一下,以供将来可能的快速参考——前导斜杠将匹配锚定到根。因此,在下面的示例中,如果没有斜杠,通配符也会排除 foo 中的所有内容,因为它将采用
*
并沿树递归移动。但是,使用 /*
,它会排除除文件夹 foo 及其内容之外的所有内容:
$ cat .gitignore
/*
!/foo
您已经完全回答了自己的问题。如果您更仔细地查看 github/gitignore 存储库,您会发现大多数文件对于如何编写模式使用不一致的规则;很可能大部分都是由那些不像您那样费心阅读文档或测试的人贡献的。
所以,如果这有帮助:你是对的,要有信心。
如果您在此类协作项目中发现错误,请毫不犹豫地贡献您的知识。如果您需要进一步增强信心,甚至还有一些先例。
自从添加问题以来,它可能已经更新,但我认为docs相当清楚。特别是
例如,模式 doc/frotz/ 匹配 doc/frotz 目录,但不匹配 /doc/frotz 目录;然而 frotz/ 匹配 frotz 和 a/frotz ,它是一个目录(所有路径都是相对于 .gitignore 文件的)。
以及示例部分,
模式 doc/frotz 和 /doc/frotz 在任何 .gitignore 文件中具有相同的效果。换句话说,如果模式中已经存在中间斜杠,则前导斜杠不相关。