简体   繁体   English

.gitignore 排除不适用于单个文件

[英].gitignore exclusion is not working for a single file

$ git --version
git version 2.6.4

I realize this is a duplicate but the other question's answers have not helped.我意识到这是重复的,但其他问题的答案没有帮助。

Folder structure文件夹结构

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

I want to ignore everything in dist except samples and README.md.我想忽略除示例和 README.md 之外的 dist 中的所有内容。 My first few tries at it didn't work, so I settled on just unignoring the README:我的前几次尝试没有奏效,所以我决定只忽略自述文件:

dist
!dist/samples/README.md 

README is a brand new file. README 是一个全新的文件。 The dist folder is not in source control at all. dist 文件夹根本不在源代码管理中。 But when I check ignore, it's still being ignored:但是当我检查忽略时,它仍然被忽略:

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

I've tried:我试过了:

  1. changing the order of the ignores改变忽略的顺序
  2. removing the slash from the beginning of the line从行首删除斜线
  3. adding a ** in the middle: dist/**/README.md在中间添加一个**: dist/**/README.md
  4. adding a /* to the end of dist on the first line在第一行的dist末尾添加一个/*

The only other things being ignored are *.js, *.js.map, temp and node_modules.唯一被忽略的其他内容是 *.js、*.js.map、temp 和 node_modules。 The funny thing is that Webstorm thinks that the file is not being ignored (it changes color) but the command line tool does think it is being ignored.有趣的是,Webstorm 认为文件没有被忽略(它会改变颜色),但命令行工具确实认为它被忽略了。

I don't see what I'm doing wrong.我不明白我做错了什么。 The pattern seems very simple:模式看起来很简单:

  1. ignore all the things in this directory忽略此目录中的所有内容
  2. don't ignore this one thing here不要忽略这里的一件事

But it's clearly not working.但它显然不起作用。

The problem is simply because you are ignoring the directory dist .问题仅仅是因为您忽略了目录dist So Git will no longer look into the directory to look for other files.因此 Git 将不再通过查看目录来查找其他文件。

As explained in this related answer , you need to whitelist the directory and only ignore its contents.如此相关答案中所述,您需要将目录列入白名单,仅忽略其内容。 Since you are having a nested structure, this does end up being a bit complicated though:由于您具有嵌套结构,因此最终确实有点复杂:

# 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

This is also explicitly mentioned in the gitignore documentation (emphasis mine): gitignore 文档中也明确提到了这一点(重点是我的):

An optional prefix " ! " which negates the pattern;一个可选的前缀“ ! ”,它否定了模式; any matching file excluded by a previous pattern will become included again.被先前模式排除的任何匹配文件将再次包含在内。 It is not possible to re-include a file if a parent directory of that file is excluded.如果排除了该文件的父目录,则无法重新包含该文件。 Git doesn't list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined.出于性能原因,Git 不会列出排除的目录,因此包含文件的任何模式都不起作用,无论它们在哪里定义。

I has the similar problem with another .gitignore in subdirectory.我在子目录中的另一个 .gitignore 也有类似的问题。 For examaple:例如:

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

In root .gitignore where two rules:在根.gitignore ,有两条规则:

*.js
!gulpfile.js

And in Subdir/gulpfile.js where another one rule:Subdir/gulpfile.js ,另一个规则是:

*.js

Because of that, Subdir/gulpfile.js where ignored.因此,忽略了Subdir/gulpfile.js To solve problem it is required to remove Subdir/.gitignore , or add !gulpfile.js to Subdir/.gitignore .要解决问题,需要删除Subdir/.gitignore ,或将!gulpfile.js添加到!gulpfile.js Subdir/.gitignore

tl;dr: tl;博士:

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

Proof it works:证明它有效:

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

Like https://stackoverflow.com/a/35279076/2496472 says, the docs mention:就像https://stackoverflow.com/a/35279076/2496472说的,文档提到:

An optional prefix " ! " which negates the pattern;一个可选的前缀“ ! ”,它否定了模式; any matching file excluded by a previous pattern will become included again.被先前模式排除的任何匹配文件将再次包含在内。 It is not possible to re-include a file if a parent directory of that file is excluded.如果排除了该文件的父目录,则无法重新包含该文件。 Git doesn't list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined.出于性能原因,Git 不会列出排除的目录,因此包含文件的任何模式都不起作用,无论它们在哪里定义。

However, the docs also say:但是,文档还说:

Two consecutive asterisks (" ** ") in patterns matched against full pathname may have special meaning:与完整路径名匹配的模式中的两个连续星号(“ ** ”)可能具有特殊含义:

  • A slash followed by two consecutive asterisks then a slash matches zero or more directories.斜杠后跟两个连续的星号,然后斜杠匹配零个或多个目录。 For example, " a/**/b " matches " a/b ", " a/x/b ", " a/x/y/b " and so on.例如,“ a/**/b ”匹配“ a/b ”、“ a/x/b ”、“ a/x/y/b ”等。

Putting this together, the strategy is to never ignore a directory but ignore all files within a directory, and then exclude the file you want.把这些放在一起,策略是永远不要忽略一个目录,而是忽略一个目录中的所有文件,然后排除你想要的文件。

References:参考:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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