什么时候在 gitignore 中使用前斜杠

我正试图更清楚地理解 .gitignore语法,特别是关于 https://github.com/github/gitignore gitignores。

我看到前面的斜杠只用于匹配相对于 .gitignore文件位置(来自 http://git-scm.com/docs/gitignore)的路径名:

前斜杠匹配路径名的开头,例如,“/* . c”匹配“ cat-file.c”,但不匹配“ mozilla-sha1/sha1.c”。

但是如果我去掉前面的斜杠会发生什么呢? 据我所知,有两种情况:

  1. 如果模式不包含一个斜杠(或者它只包含一个尾部斜杠,这意味着它应该匹配一个目录) ,搜索将在整个目录树中执行。例如,模式 dir/将匹配 <root>/dir<root>/a/dir<root>/a/b/c/.../dir等,其中 <root>.gitignore文件的位置。
  2. 如果模式包含一个斜杠,它不在尾随位置(它不是最后一个字符) ,那么它只与相对于 .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一致: 模式中有一些斜杠,因此它被认为是从根目录开始的路径名。

现在该问真正的问题了。让我们考虑一下 这个吉蒂诺档案: 例如,当它们忽略目录 downloader/时,它们是否实际上忽略了在整个目录树中找到的每一个 downloader目录?自从我之前看到 Git 的工作原理后,我就开始这么想了。

因此,如果我碰巧有一个自定义模块,其中包含一个 downloader目录,这个模块会像 Magento 根目录中的常规模块一样被意外忽略吗?这是一个有点讽刺意味的问题,因为它实际上已经发生在我身上,产生了一个非常难以找到的 bug。

因此,在 Magento .gitignore文件中(我只是作为一个例子提到) ,很多模式包含斜杠,所以它们与从根目录开始的路径名正确匹配,但是有一些情况,如 downloader/errors/,如果我没有弄错,是潜在的危险,它们可能应该更改为 /downloader//errors/

作为一个更一般的问题,当我想要显式地从 root 开始选择一个路径名,而不是用它来选择包含斜杠的模式时,我是否应该总是使用前斜杠来表示不包含斜杠的模式(除了后面的那个) ,或者为了清晰起见,我是否应该总是使用前斜杠?你觉得怎么样?

感谢您的阅读,并为长期职位抱歉。

20578 次浏览

你已经完全回答了你自己的问题。如果你更仔细地观察 github/gitignore repo,你会发现大多数文件在如何编写模式方面使用了不一致的规则; 很可能大多数文件是由那些不像你那样费心阅读文档或测试内容的人提供的。

所以如果这有帮助的话: 你是对的,要自信。

如果您在这样的协作项目中看到错误,请毫不犹豫地贡献您的知识。如果你需要进一步建立信心,甚至还有 一些先例

只是想总结一下,以备将来参考——前面的斜杠将匹配锚定到根目录。因此,在下面的例子中,如果没有斜杠,通配符也会排除 foo 中的所有内容,因为它会接受 *并在树中递归地移动。但是,对于 /*,它排除了文件夹 foo 及其内容之外的所有内容:

$ cat .gitignore
/*
!/foo