[英]Git failing to ignore files in subdirectory
My.gitignore 文件似乎并没有忽略我想要的所有文件。
==================上下文==================
在我的 git 存储库中,我有几个子目录,类似于这个简化的示例:
git base folder
> .gitignore
> Folder A
> Folder B
> Subfolder B0
>SubSubfolder B0a
> Files
> Subfolder B1
> SubSubfolder B1a
> Files
> File B1b.ft0
> File B1c.ft0
> File B1d.ft1
> File B1e.ft2
> Etc
我想忽略子文件夹B1
中的所有文件,除了(比如说)文件B1b.ft0
和文件B1e.ft2
。 我还想忽略 SubSubfolder B1a
和B0a
中的所有文件。 在我的.gitignore
文件(只有一个)中,我有以下几行:
#Ignore:
B1/**
B1a/
B0a/
#Include
!B1/B1b.ft0
!B1/B1e.ft2
但是,子文件夹B1
中的所有文件都包括在内。 SubSubfolder B1a
中的文件被忽略,但是 SubSubfolder B0a
中的文件不是。
============== 尝试的解决方案 ==============
我决定首先解决子文件夹B1
中未忽略文件的问题:
我在.gitignore
文件中尝试了B1/
,但这忽略了那里的所有文件,包括我想要保留的文件。
我也尝试过B1/*
和B1/*.*
,但它们都无法忽略文件夹B1
中的其他文件。
然后我尝试手动列出我想忽略/保留在此文件夹中的所有文件。 这行得通,但是有很多文件,它们可能会改变。 我不想使用这个选项。
==================方法==================
在测试每个选项是否有效时,我使用git check-ignore -v <filename>
和git status --ignore
。 我还使用git rm --cached -r.
然后是git add -A
以清除忽略文件的存储库。 (子问题:我需要提交.gitignore
才能生效吗?)
==================总结==================
我越来越对此感到困惑和烦恼,有人可以帮助我吗? (我是否只需要在整个地方应用大量的 * 就可以自动开始工作, 就像在这个问题中一样?)
还请解释为什么以及如何,您的解决方案有效,而我的解决方案无效(如果您知道的话)。
经过大量测试、阅读文档(非常好)并询问其他人,我终于找到了解决方案。 (是的,它确实涉及在各处喷洒大量*)。 我会尽力解释我认为发生了什么,以及如何避免它。
Git 没有忽略子文件夹B1
中的文件,因为它希望B1
位于根目录中。 将 .gitignore 条目更改为**/B1/**
、 .**/B1/B1b.ft0
和.**/B1/B1e.ft2
解决了问题。
理解这个问题的关键是理解 .gitignore 语法的一些奇怪之处。 幸运的是,没有太多要学习的东西,即使其中一些令人沮丧地晦涩难懂——例如,您可能知道 gitignore 文件是向下读取的,这会导致这种行为:
foo 没有被忽略 |
foo 被完全忽略 |
---|---|
富 |
!富 |
我的问题与 .gitignore 语法中另一个神秘的微妙之处有关:它如何解析文件路径。 gitignore 目录分隔符是/
,但是根据它在一行中的位置,或者有多少,它的行为方式完全不同:
对于只有一个/
的条目:
/ 在行尾,如foo/ |
/ 在行的中间,如foo/bar |
/ 在行首,如/foo |
---|---|---|
Git 忽略每个名为foo 的目录,无论它有多深的子目录。 |
Git 忽略文件路径<.gitignore_directory>/foo/ 中名为bar 的任何文件夹和文件。 名为foo/bar 的文件夹(或文件)只有在具有特定文件路径的情况下才会被忽略,即该路径从与 .gitignore 文件相同的目录开始。 |
Git 忽略任何名为foo 的文件和文件夹,但前提是它们与 .gitignore 文件位于同一目录中。 |
对于有多个/
的条目,规则是上述规则的组合。 几个例子说明:
/foo/ |
foo/bar/ |
/foo/bar |
---|---|---|
此模式仅匹配一项:与 .gitignore 位于同一文件夹中的子文件夹,名为foo 。 (当然,里面的所有东西也都被忽略了。) |
此模式也只匹配一个项目,即在文件夹foo 中找到的名为bar 的子子文件夹,它本身必须是也包含 .gitignore 文件的文件夹的子文件夹。 |
此模式与中间示例中的模式相同,除了它还可以忽略名为bar 的文件,而不仅仅是目录。 |
在上述所有情况下,任何被忽略的目录foo
中的文件和子目录都不能被例如!foo/bar
忽略。
狡猾的微妙之处在于,像foo/
/
的行末尾的 / 将导致任何名为foo
的目录被忽略,无论其深度如何,但在/
之后放置任何字符(包括通配符!),或放置任何其他/
在同一行中将意味着它仅与找到 .gitignore 的路径相关。 那么,如何才能忽略子目录中的文件呢?
解决方法是更好地使用通配符。 .gitignore 语法中有三个通配符:
?
- 匹配 1 个或多个字符,除了/
。 几乎只用于文件名匹配。*
- 匹配 0 个或多个字符,除了/
**
- 匹配 0 个或多个字符,包括/
。 ?
或*
可用于忽略目录中的所有文件,但不能忽略子文件夹。 如果foo
与 .gitignore 位于同一目录中,则以下示例都将忽略子目录foo
中的所有文件。
foo/*
foo/?
这不会忽略名称为 0 字符的文件。 但是,请注意,这些不会忽略例如<.gitignore_directory>/filepath/foo
中的文件。
由于**
匹配目录,它可以像这样解决上述问题: **/foo/
。 即使/
之后有一个非空白字符,这也会忽略所有名为foo
的目录和子目录,因为**/
匹配所有文件路径。
**/foo/?
忽略任何目录foo
中的所有命名文件。foo/**/bar.txt
忽略名为foo
的文件夹中任意深度的每个名为bar.txt
的文件,其中foo
位于<.gitignore_directory>
中。**/foo/**
忽略每个目录foo
中的所有内容,但不忽略目录本身,因此我可以取消忽略其中的 select 几个文件!耶。 我的问题得到了回答——几乎。
对于 my.gitignore 中的条目忽略 SubSubfolder B0a
,我实际上有一些与我所要求的略有不同的东西。 在我的实际项目中, B0a
被称为.generated_files
。 我不完全确定 git 会如何看待以点开头的 .gitignore 条目,所以我在它前面加上了一个斜杠,如下所示: /.generated_files/
。 (我在写问题时忘记了这一点。)正如我现在所知,这导致 git 只期望它在根目录中,因此错过了它。 我还了解到,如果条目以.
.
尽管在我的情况下它没有引起问题,但我还发现 .gitignore 文件中的条目将同时匹配文件和文件夹。 因此,如果您有一个名为 foo 的文件和一个名为 foo 的文件夹,将foo
放入 .gitignore 会导致它们都被忽略。
希望这个答案对您有所帮助,恐怕阅读官方文档可能会更容易理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.