繁体   English   中英

Git 无法忽略子目录中的文件

[英]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 B1aB0a中的所有文件。 在我的.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 几个文件!

耶。 我的问题得到了回答——几乎。

关于子子文件夹 B0a:

对于 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM