gitignore 中 * 和 /* 的区别

difference between * and /* in gitignore

我发现 /** 在比较设置时有不同的含义:

*

!/init.el
!/README.md
!.gitignore
!/lib/

VS

/*

!/init.el
!/README.md
!.gitignore
!/lib/

前者不追踪/lib/但后者追踪

如何理解*/*

更新
我认为这个问题与另一个问题不完全相同。因为他专注于 dir/**dir/* 而这个专注于 /**

第一个版本忽略除明确列出的文件之外的所有文件。 lib 被忽略,因为它不包含可跟踪的文件。 Git 不跟踪文件夹,因此显示为空的目录似乎会被忽略。

第二个版本忽略除明确列出的所有根级文件和目录。它 not 忽略根目录中任何可跟踪的内容和 notlib 已明确列出,因此不会被忽略。它包含的任何文件都不在根级别,因此也不会被忽略。

答案有点复杂,因为 Git 的扫描算法很棘手,但归结为 * 匹配 lib/custom-file.el/* 匹配不是。

作为一般规则,在 glob 模式中,* 不会 "cross" 路径名分隔符 /-es。因此 A*B 匹配 ANameThatEndsInB 但不匹配 ADirectory/WithAFileB.

/ 放在 glob 模式中需要 / 之前的内容命名目录,而 / 之后的内容出现在目录中:A*/*B 匹配 ADirectory/WithAFileB。名称组件 ADirectoryWithAFileB 分别与全局组件 A**B.

匹配

ending/ 中的 glob 模式与在 */ 中一样,仅匹配 目录。一个 starting with / 在 Git 中有另一个特殊含义(但请注意,例如 .gitignore 条目 /foo/bar/ 由两个组件:/foo/ 然后是 bar/bar/ 部分 以斜杠开头)。特别是,如果模式以 / 开头,它仅适用于 Git 目录的顶级文件。如果那是顶层 .gitignore 那么这意味着 work-tree 本身的根。

现在,与 一样,如果 Git 在一个目录中没有现有的 tracked 文件,那么 Git 就不会有时必须阅读那个目录。与目录名称匹配的忽略模式将使 Git 跳过 目录扫描,如果 Git 由于某些其他原因尚未扫描该目录.所以一般来说,如果你有一个 .gitignore 在任何地方都有 * ,任何目录都会被完全跳过——好吧,只要 Git 不需要查看出于其他原因。因此 .gitignore 中的 * 倾向于忽略所有目录。但是,Git 的忽略规则指出,每当 Git 拥有文件或目录名称并正在检查 .gitignore 个文件时,它应该通读 整个文件 并找到 所有 匹配项,包括前面带有 ! 的匹配项。这意味着,例如:

*
!*/

将告诉 Git 忽略所有内容(包括目录),但通过说 不要 忽略 */ 目录来覆盖它。但是 * 将继续忽略所有文件。

如果你把它写成:

/*
!/*/

您将忽略此目录(包含 .gitignore 的目录)中的所有文件,但 Git 扫描其所有子目录。任何 sub-directory 中的所有内容,例如 foo/name 将无法匹配这些 glob 模式中的任何一个,因为 foo/name 部分有一个斜线,而 * 不能穿过它。