gitignore排除规则如何实际工作?

我试图解决一个大目录结构的gitignore问题,但为了简化我的问题,我已经减less到以下。

我有一个全新的git仓库中的两个文件(foo,bar)的以下目录结构(到目前为止没有提交):

a/b/c/foo a/b/c/bar 

显然,'git status -u'显示:

 # Untracked files: ... # a/b/c/bar # a/b/c/foo 

我想要做的是创build一个.gitignore文件,忽略/ b / c中的所有内容,但不会忽略文件“foo”。

如果我这样创build一个.gitignore:

 c/ 

然后,'git status -u'将foo和bar都显示为忽略:

 # Untracked files: ... # .gitignore 

这是我所期望的。

现在,如果我为foo添加排除规则,则:

 c/ !foo 

根据gitignore手册,我希望这个工作。 但它不 – 它仍然忽略foo:

 # Untracked files: ... # .gitignore 

这也不起作用:

 c/ !a/b/c/foo 

这也不是:

 c/* !foo 

得到:

 # Untracked files: ... # .gitignore # a/b/c/bar # a/b/c/foo 

在这种情况下,虽然foo不再被忽略,但bar也不被忽略。

.gitignore中的规则的顺序似乎也不重要。

这也不符合我的期望:

 a/b/c/ !a/b/c/foo 

那个忽略了foo和bar。

一种情况是,如果我创build文件a / b / c / .gitignore并放在那里:

 * !foo 

但是这个问题最终会在/ b / c下面有其他的子目录,我不希望把每个单独的.gitignore放在每一个子目录中 – 我希望创build一个“基于项目”的.gitignore文件可以放在每个项目的顶层目录中,并覆盖所有“标准”子目录结构。

这似乎也是相同的:

 a/b/c/* !a/b/c/foo 

这可能是我能够实现的“最有效的工作”,但是需要说明完整的相对path和显式的exception,如果我在不同层次上有很多名为“foo”的文件,这将是一个痛苦的子目录树。

无论如何,我不太明白排除规则是如何工作的,或者当目录(而不是通配符)被忽略时,它们根本就不起作用 – 通过以/

任何人都可以摆脱这个光?

有没有办法让gitignore使用正则expression式而不是这种笨拙的基于shell的语法?

我使用git-1.6.6.1在Ubuntu / bash3的Cygwin / bash3和git-1.7.1上观察。

  / A / B / C / *
 !FOO 

似乎为我工作(Linux上的git 1.7.0.4)。 *是重要的,否则你忽略目录本身(所以git不会在里面),而不是目录中的文件(这允许排除)。

认为排除是“但不是这个”而不是“但包括这个” – “忽略这个目录( /a/b/c/ )而不是这个( foo )”没有多大意义; “忽略此目录中的所有文件( /a/b/c/* ),但不包含这个( foo )”。 引用手册页:

一个可选的前缀! 否定了这种模式; 任何先前模式排除的匹配文件将再次包含在内。

即该文件已经被排除了,已经被再次包括在内。 希望能够stream露出一些光芒。

我有类似的情况,我的解决scheme是使用:

 /a/**/* !/a/**/foo 

这应该适用于任意数量的中间目录,如果我正确地阅读**

这是另一个select:

 * !/a* !/a/* !/a/*/* !/a/*/*/* 

这将忽略每个文件和目录,除了文件/目录三个层次以内。

这绝对不是从.gitignore手册页中清楚的。 这工作:

 * !/a !/a/b !/a/b/c !/a/b/c/foo # don't forget this one !.gitignore 

正如克里斯提到的,如果一个目录被排除,它甚至不会被打开。 所以,如果你想能够忽略*但是一些文件,你必须build立这些文件的path如上。 对我来说这很方便,因为我想对库的1个文件做一个代码审查,如果我想稍后再做一个,我只是将其添加,而其他所有内容都将被忽略。

在一个更通用的说明, git1.8.2将包括从亚当斯皮尔斯有关确定哪个gitignore规则实际上忽略您的文件的修补程序 (也在其v4中 , 由一些堆栈溢出问题提示 )。

请参阅git1.8.2发行说明和SO问题“ 哪个gitignore规则忽略我的文件 ”:
那将是命令git check-ignore