.gitignore中的否定模式是如何工作的?

136

我正在尝试使用带有否定模式(以!开头的行)的.gitignore文件,但它没有按照我期望的方式工作。

作为最简单的例子,我有以下目录结构:

C:/gittest
 -- .gitignore
 -- aaa/
   -- bbb/
     -- file.txt
   -- ccc/
     -- otherfile.txt

而在我的gitignore文件中,我有这个:

aaa/
!aaa/ccc/

根据这个文档页面,我的理解是文件aaa/ccc/otherfile.txt不应该被忽略,但事实上git正在忽略aaa下的所有内容。

我是否误解了这个句子:"一个可选的前缀!可以否定模式; 任何由先前的模式排除的匹配文件将再次包括在内。"?

顺便说一句,这是在Windows上使用msysgit 1.7.0.2。

3个回答

228

我认为你实际想要做的是:

aaa/*
!aaa/ccc
你告诉它“不要查找aaa”,所以它甚至不会检查路径aaa/ccc。如果你使用通配符,它仍然读取aaa的内容,然后每个条目都匹配通配符并被忽略,除了aaa/ccc被放回去。

2
@iconoclast:那么你很可能在做一些不同的事情。如果你需要帮助,请发布另一个问题(提供完整信息)。 - Cascabel
这个对我也没有起作用: /apps/* !/apps/myApps/FluidTest/bin/ - Jarrod Smith
7
它是有效的;你只是在做一些不同的事情。你需要递归使用这种方法,正如答案中给出的原因一样。应用程序路径包括“apps/myApps”,“apps/myApps/*”等等。 - Cascabel
为什么 aaa/**/* !aaa/ccc/eee 的处理方式无效?(忽略除特定路径下的文件以外的一切) - Phương Nguyễn
同样的概念适用于子目录:忽略aaa//,因此永远不会读取aaa/ccc/的内容,因此永远不匹配!aaa/ccc/eee -- 同样适用于 !/apps/myApps/FluidTest/bin/。要忽略除特定子文件夹以外的所有内容,您必须以以下方式重新忽略和取消忽略整个树的所有级别:(aaa/ !aaa/ccc aaa/ccc/ !aaa/ccc/eee) (/apps/ !/apps/myApps /apps/myApps/ !/apps/myApps/FluidTest /apps/myApps/FluidTest/* !/apps/myApps/FluidTest/bin)。 请参见实际示例 - Céline de Roland

29
如果您想排除 aaa 中的所有内容,但包括 aaa/ccc 及其下属所有内容,则应使用:
aaa/*
!aaa/ccc
!aaa/ccc/*

第一行告诉Git忽略aaa下的所有内容,第二行告诉它不要忽略文件夹aaa/ccc,实际上这使得第三行生效,它告诉Git不要忽略aaa/ccc下的所有内容。


1
第三行对我没有影响。 - James Hopkin
6
为了能够包含 aaa/ccc 任何层级下的所有子目录中的所有内容,我使用了 !aaa/ccc/** 而不是 !aaa/ccc/*。请注意,这并未改变原意,只是使表述更加通俗易懂。 - boclodoa

6

如果在运行git status命令时,某些已取消忽略的文件未显示,可以先运行git update-index命令,这样Git就能看到更改了(至少在1.9.x版本的Git Bash中是这个情况)。


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