.gitignore排除规则实际上是如何工作的?

ttvkxqim  于 2022-12-17  发布在  Git
关注(0)|答案(5)|浏览(121)

我正试图解决一个大目录结构上的gitignore问题,但为了简化我的问题,我将其简化为以下内容。
在一个全新的git仓库中,我有两个文件(foo,bar),目录结构如下(目前还没有提交):

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

显然,git status -u显示:

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

我想要做的是创建一个.gitignore文件,忽略a/B/c中的所有内容,但不忽略foo文件。
如果我这样创建一个.gitignore

c/

然后git status -u显示foobar都被忽略:

# 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

这个函数忽略了foobar
有一种情况确实有效,那就是我创建了a/B/c/.gitignore文件,并在其中放入:

*
!foo

但这样做的问题是,最终a/b/c下会有其他子目录,我不想在每个子目录中放置一个单独的.gitignore-我希望创建 * 基于项目的 * .gitignore文件,这些文件可以位于每个项目的顶层目录中,并覆盖所有“标准”子目录结构。
这似乎也是等价的:

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

这可能是我能做到的最接近“工作”的事情,但是需要声明完整的相对路径和显式异常,如果在子目录树的不同级别中有很多名为foo的文件,这将是一件痛苦的事情。
无论如何,要么我不太理解排除规则是如何工作的,要么当目录(而不是通配符)被忽略时,它们根本不起作用--通过一个以/结尾的规则。
有人能解释一下吗?
有没有办法让gitignore使用一些合理的东西,比如正则表达式,来代替这种笨拙的基于shell的语法?
我在Cygwin/bash 3上使用git-1.6.6.1,在Ubuntu/bash 3上使用git-1.7.1,并观察到了这一点。

elcex8rz

elcex8rz1#

/a/b/c/*
!foo

似乎对我有用(Linux上的git 1.7.0.4)。*很重要,因为否则你会忽略目录本身(这样git就不会查看里面),而不是目录中的文件(允许排除)。
将排除项看作是“但不是这个”而不是“但包括这个”-“忽略这个目录(/a/b/c/)但不是这个目录(foo)”没有多大意义;“忽略此目录(/a/b/c/*)中的所有文件,但不忽略此目录(foo)”。
一个可选的前缀!,用于否定模式;被先前模式排除的任何匹配文件将再次被包括。
也就是说,* 文件 * 必须已经被排除才能再次被包含。希望这能提供一些启示。

fdbelqdn

fdbelqdn2#

我有类似的情况,我的解决方案是用途:

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

如果我正确读取了**,那么这应该适用于任意数量的中间目录。

cdmah0mi

cdmah0mi3#

这里是另一个选项:

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

这将忽略每个文件和目录,但不包括中三层深的文件/目录。

jfewjypa

jfewjypa4#

这一点在.gitignore手册页中肯定是不清楚的。

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

# don't forget this one
!.gitignore

正如Chris所提到的,如果目录被排除,它甚至不会被打开。所以如果你想忽略 *,但是忽略一些文件,你必须如上所述构建这些文件的路径。对我来说,这很方便,因为我想对库中的一个文件做代码评审,如果我想稍后做另一个文件,我只需要添加它,其他所有的都被忽略。

fgw7neuy

fgw7neuy5#

一般来说,git1.8.2会包含Adam Spiers中的patch(也可以是in its v4prompted by some Stack Overflow question),用于确定哪个gitignore规则实际上忽略了你的文件。
参见git1.8.2 release notes和销售订单问题“which gitignore rule is ignoring my file“:
这将是命令git check-ignore

相关问题