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

发布于 2024-09-04 19:18:38 字数 1902 浏览 10 评论 0原文

我正在尝试解决大型目录结构上的 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 -ufoobar 显示为忽略:

# 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

该忽略了 foobar

一种可行的情况是,如果我创建文件 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

神经暖 2024-09-11 19:18:38
/a/b/c/*
!foo

似乎对我有用(Linux 上的 git 1.7.0.4)。 * 很重要,否则您将忽略目录本身(因此 git 不会查看内部)而不是目录中的文件(允许排除)。

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

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

即,文件必须已被排除才能再次包含。希望这能带来一些启发。

/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:

An optional prefix ! which negates the pattern; any matching file excluded by a previous pattern will become included again.

i.e., the file has to have been excluded already to be included again. Hope that sheds some light.

誰認得朕 2024-09-11 19:18:38

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

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

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

I have a similar situation, my solution was to use:

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

That should work for an arbitrary number of intermediate directories if I read ** correctly.

甚是思念 2024-09-11 19:18:38

这是另一个选项:

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

这将忽略每个文件和目录,除了 a 中深度三层的文件/目录。

Here is another option:

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

That would ignore every file and directory, except files/directories three levels deep within a.

π浅易 2024-09-11 19:18:38

从 .gitignore 手册页中绝对不清楚这一点。这是有效的:

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

# don't forget this one
!.gitignore

正如 Chris 所提到的,如果目录被排除,甚至不会打开。因此,如果您希望能够忽略 * 但某些文件,则必须如上所述构建这些文件的路径。对我来说这很方便,因为我想对库的 1 个文件进行代码审查,如果我想稍后再做另一个文件,我只需添加它,其他所有内容都会被忽略。

this is definitely not clear from the .gitignore man page. This works:

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

# don't forget this one
!.gitignore

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.

掐死时间 2024-09-11 19:18:38

更一般地说,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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文