假设您的项目目录中有以下结构
./
├── foo/
│ └── foo
├── bar/
│ └── baz
├── docs/
│ └── release/
│ └── 0.0.1
├── README.md
└── src/
└── code
其中目录 foo/ 和 bar/ 是构建结果(您不想跟踪)的示例,它们具有不可预测的名称(或者难以在 .gitignore 中单独明确列出或具有足够窄的模式),而docs/ 和src/ 包含(仅)要跟踪的文件(和子目录),并且您还想直接跟踪存储库根目录中的任何文件(例如当前的README.md)。
这可以通过以下 .gitignore 实现:
# Ignore all subirectories (but not files in the repo root dir):
*/
# ... except for the actual project sub dirs:
!src/
!docs/
解释
请参阅the documentation(也可通过git help gitignore获得)了解.gitignore 中的模式如何工作以及它们如何相互交互。这是上面解决方案中使用的那些:
* 匹配除斜杠(/,用作目录分隔符)以外的任何内容,因此匹配任何级别的任何目录名或文件名。这有点太宽泛了,因为我们不想忽略根目录中的文件。附加 / 使模式仅匹配目录,因此 */ 匹配任何目录(任何级别)。 (忽略目录中的文件也将被忽略,因为 Git 本身不会跟踪目录。)
所以对于*/,我们忽略了整个文件树,除了直接在根目录中的文件。
但这仍然太多了。所以我们需要有选择地撤消一些忽略。我们可以通过额外的模式来做到这一点:前缀!“否定”一个模式;任何被先前模式(此处为*/)排除的匹配文件都将再次包含在内。但,因为如果排除了该文件的父目录,则不可能重新包含该文件(出于性能原因,Git 不会列出排除的目录,因此包含文件的任何模式都无效,无论它们在哪里定义。 ), docs/ 和 src/ 将只匹配顶级目录 docs 和 src,但不匹配 foo/src 以防存在。
这有点晦涩难懂,因此人们可能更愿意通过在前面添加 / 来明确地将否定模式锚定到根目录:
# Ignore all subirectories (but not files in the repo root dir):
*/
# ... except for the actual source dirs:
!/src/
!/docs/