.gitignore 排除规则实际上是如何运作的?
我正在尝试解决大型目录结构上的 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
将 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
不再被忽略, < code>bar 也不会被忽略。
.gitignore
中的规则顺序似乎也不重要。
这也没有达到我的预期:
a/b/c/
!a/b/c/foo
该忽略了 foo
和 bar
。
一种可行的情况是,如果我创建文件 a/b/c/.gitignore 并将其放入其中:
*
!foo
但这样做的问题是,最终在 a/b/c
下还会有其他子目录我不想将单独的 .gitignore
放入每个单独的文件中 - 我希望创建基于项目 .gitignore
文件可以位于每个项目的顶级目录中,并覆盖所有“标准”子目录结构。
这似乎也是等价的:
a/b/c/*
!a/b/c/foo
这可能是我能实现的最接近“工作”的事情,但是需要说明完整的相对路径和显式异常,如果我有很多文件,这将是一件痛苦的事情name foo
位于子目录树的不同级别中。
不管怎样,要么我不太明白排除规则是如何工作的,要么当目录(而不是通配符)被以 /
结尾的规则忽略时,它们根本不起作用。
谁能解释一下吗?
有没有办法让 gitignore 使用像正则表达式这样合理的东西,而不是这种笨拙的基于 shell 的语法?
我正在使用 Cygwin/bash3 上的 git-1.6.6.1 和 Ubuntu/bash3 上的 git-1.7.1 来观察这一点。
I'm trying to solve a gitignore problem on a large directory structure, but to simplify my question I have reduced it to the following.
I have the following directory structure of two files (foo, bar) in a brand new git repository (no commits so far):
a/b/c/foo
a/b/c/bar
Obviously, a git status -u
shows:
# Untracked files:
...
# a/b/c/bar
# a/b/c/foo
What I want to do is create a .gitignore
file that ignores everything inside a/b/c but does not ignore the file foo
.
If I create a .gitignore
thus:
c/
Then a git status -u
shows both foo
and bar
as ignored:
# Untracked files:
...
# .gitignore
Which is as I expect.
Now if I add an exclusion rule for foo
, thus:
c/
!foo
According to the gitignore manpage, I'd expect this to to work. But it doesn't - it still ignores foo
:
# Untracked files:
...
# .gitignore
This doesn't work either:
c/
!a/b/c/foo
Neither does this:
c/*
!foo
Gives:
# Untracked files:
...
# .gitignore
# a/b/c/bar
# a/b/c/foo
In that case, although foo
is no longer ignored, bar
is also not ignored.
The order of the rules in .gitignore
doesn't seem to matter either.
This also doesn't do what I'd expect:
a/b/c/
!a/b/c/foo
That one ignores both foo
and bar
.
One situation that does work is if I create the file a/b/c/.gitignore and put in there:
*
!foo
But the problem with this is that eventually there will be other subdirectories under a/b/c
and I don't want to have to put a separate .gitignore
into every single one - I was hoping to create project-based .gitignore
files that can sit in the top directory of each project, and cover all the "standard" subdirectory structure.
This also seems to be equivalent:
a/b/c/*
!a/b/c/foo
This might be the closest thing to "working" that I can achieve, but the full relative paths and explicit exceptions need to be stated, which is going to be a pain if I have a lot of files of name foo
in different levels of the subdirectory tree.
Anyway, either I don't quite understand how exclusion rules work, or they don't work at all when directories (rather than wildcards) are ignored - by a rule ending in a /
.
Can anyone please shed some light on this?
Is there a way to make gitignore use something sensible like regular expressions instead of this clumsy shell-based syntax?
I'm using and observe this with git-1.6.6.1 on Cygwin/bash3 and git-1.7.1 on Ubuntu/bash3.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
似乎对我有用(Linux 上的 git 1.7.0.4)。
*
很重要,否则您将忽略目录本身(因此 git 不会查看内部)而不是目录中的文件(允许排除)。将排除视为“但不是这个”而不是“但包括这个” - “忽略这个目录 (
/a/b/c/
) 但不包括这个 (foo< /code>)" 没有多大意义; “忽略此目录中的所有文件 (
/a/b/c/*
),但不忽略此文件 (foo
)”。引用手册页:即,文件必须已被排除才能再次包含。希望这能带来一些启发。
Seems to work for me (git 1.7.0.4 on Linux). The
*
is important as otherwise you're ignoring the directory itself (so git won't look inside) instead of the files within the directory (which allows for the exclusion).Think of the exclusions as saying "but not this one" rather than "but include this" - "ignore this directory (
/a/b/c/
) but not this one (foo
)" doesn't make much sense; "ignore all files in this directory (/a/b/c/*
) but not this one (foo
)" does. To quote the man page:i.e., the file has to have been excluded already to be included again. Hope that sheds some light.
我有类似的情况,我的解决方案是使用:
如果我正确读取
**
,这应该适用于任意数量的中间目录。I have a similar situation, my solution was to use:
That should work for an arbitrary number of intermediate directories if I read
**
correctly.这是另一个选项:
这将忽略每个文件和目录,除了 a 中深度三层的文件/目录。
Here is another option:
That would ignore every file and directory, except files/directories three levels deep within a.
从 .gitignore 手册页中绝对不清楚这一点。这是有效的:
正如 Chris 所提到的,如果目录被排除,甚至不会打开。因此,如果您希望能够忽略 * 但某些文件,则必须如上所述构建这些文件的路径。对我来说这很方便,因为我想对库的 1 个文件进行代码审查,如果我想稍后再做另一个文件,我只需添加它,其他所有内容都会被忽略。
this is definitely not clear from the .gitignore man page. This works:
As mentioned by Chris a directory is not even opened if it is excluded. So if you want to be able to ignore * but some files, you have to build the path to those files as above. For me this is convenient, because I want to do a code review on 1 file of a library and if I want to do another later I just add it, and all else is ignored.
更一般地说,git1.8.2将包括补丁(也在其 v4 中,由一些 Stack Overflow 问题提示)来自 Adam Spiers 关于确定哪个
gitignore< /code> 规则实际上会忽略您的文件。
请参阅 git1.8.2 发行说明 和 SO 问题“哪个 gitignore 规则忽略我的文件":
这将是命令
git检查-忽略
。On a more general note, git1.8.2 will include the patch (also in its v4, prompted by some Stack Overflow question) from Adam Spiers about determining which
gitignore
rule actually ignores your file.See git1.8.2 release notes and the SO question "which gitignore rule is ignoring my file":
that will be the command
git check-ignore
.