【问题标题】:.gitignore exclusion is not working for a single file.gitignore 排除不适用于单个文件
【发布时间】:2016-05-18 15:52:01
【问题描述】:
$ git --version
git version 2.6.4

我意识到这是重复的,但其他问题的答案没有帮助。

文件夹结构

/
-- dist/
---- samples/ 
---- README.md
---- foo/
---- bar/
---- baz.js 

我想忽略 dist 中的所有内容,除了示例和 README.md。我最初的几次尝试都没有成功,所以我决定忽略自述文件:

dist
!dist/samples/README.md 

README 是一个全新的文件。 dist 文件夹根本不在源代码管理中。但是当我检查忽略时,它仍然被忽略:

$ git check-ignore dist/samples/README.md 
dist/samples/README.md
$ git check-ignore src
   # empty line    

我试过了:

  1. 更改忽略的顺序
  2. 从行首删除斜线
  3. 在中间加一个**:dist/**/README.md
  4. 在第一行的dist 末尾添加/*

唯一被忽略的其他内容是 *.js、*.js.map、temp 和 node_modules。有趣的是,Webstorm 认为文件没有被忽略(它改变颜色),但命令行工具确实认为它被忽略了。

我看不出我做错了什么。模式看起来很简单:

  1. 忽略此目录中的所有内容
  2. 这里不要忽视这一点

但它显然不起作用。

【问题讨论】:

    标签: git macos bash


    【解决方案1】:

    tl;博士:

    /dist/**/*.*
    !/dist/**/README.md
    !/dist/samples/*.*
    
    

    证明它有效:

    tree dist -a
    dist
    ├── bar
    │   └── index.html
    ├── baz.js
    ├── foo
    │   └── main.js
    └── samples
        ├── README.md
        └── stuff.jpg
    
    find dist -type f | git check-ignore --verbose --non-matching --stdin
    .gitignore:1:/dist/**/*.*   dist/baz.js
    .gitignore:2:!/dist/samples/*.* dist/samples/stuff.jpg
    .gitignore:2:!/dist/samples/*.* dist/samples/README.md
    .gitignore:1:/dist/**/*.*   dist/foo/main.js
    .gitignore:1:/dist/**/*.*   dist/bar/index.html
    

    就像https://stackoverflow.com/a/35279076/2496472 所说,文档提到:

    一个可选前缀“!”否定模式;任何被先前模式排除的匹配文件都将再次包含在内。如果排除了该文件的父目录,则无法重新包含该文件。出于性能原因,Git 不会列出排除的目录,因此包含文件的任何模式都无效,无论它们是在哪里定义的。

    但是,文档也说:

    与完整路径名匹配的模式中的两个连续星号(“**”)可能具有特殊含义:

    • 斜杠后跟两个连续的星号,然后斜杠匹配零个或多个目录。例如,“a/**/b”匹配“a/b”、“a/x/b”、“a/x/y/b”等。

    综上所述,策略是从不忽略目录,而是忽略目录中的所有文件,然后排除你想要的文件。

    参考资料:

    【讨论】:

      【解决方案2】:

      我对子目录中的另一个 .gitignore 也有类似的问题。例如:

      - root
      -- Subdir
      --- gulpfile.js
      --- .gitignore
      -- .gitignore
      

      在根.gitignore 里面有两条规则:

      *.js
      !gulpfile.js
      

      而在Subdir/gulpfile.js 中还有另一条规则:

      *.js
      

      因此,Subdir/gulpfile.js 被忽略。解决问题需要删除Subdir/.gitignore,或将!gulpfile.js添加到Subdir/.gitignore

      【讨论】:

        【解决方案3】:

        问题仅仅是因为您忽略了目录dist。所以 Git 将不再去目录中寻找其他文件。

        正如this related answer 中所述,您需要将该目录列入白名单,并且只忽略其内容。由于你有一个嵌套结构,这最终会有点复杂:

        # ignore everything in the `dist` folder
        dist/*
        # … but don’t ignore the `dist/samples` folder
        !dist/samples/
        # … but ignore everything inside that `dist/samples` folder
        dist/samples/*
        # … except the `README.md` there
        !dist/samples/README.md
        

        gitignore documentation(强调我的)中也明确提到了这一点:

        一个可选前缀“!”否定模式;任何被先前模式排除的匹配文件都将再次包含在内。 如果该文件的父目录被排除,则无法重新包含该文件。 Git 出于性能原因不会列出排除的目录,因此包含文件的任何模式都无效,无论如何它们是在哪里定义的。

        【讨论】:

        • 是的,你是对的,刚刚解决了这个问题;从逻辑上讲,这令人困惑;我告诉它忽略目录中的所有东西,除了一件事,但 git 说“不,抱歉,忽略目录优先”
        • 我同意这有点烦人,但不幸的是 Git 在这里的行为方式:/
        • @jcollum 在文档部分很好找到,谢谢:)
        • 代码 cmets 对准确理解这里发生的事情非常有帮助。我很好奇是否有任何基于 git 版本的影响。
        • @CalebAdams 据我所知,至少在过去的 10 年里,Git 并没有使用 gitignore 语法改变其行为。所以这应该适用于你能找到的几乎任何 Git 版本。
        猜你喜欢
        • 1970-01-01
        • 2021-03-28
        • 2014-05-25
        • 1970-01-01
        • 1970-01-01
        • 2015-05-23
        • 2019-08-15
        • 2019-03-23
        • 1970-01-01
        相关资源
        最近更新 更多