使 .gitignore 忽略除少数文件之外的所有内容

Posted

技术标签:

【中文标题】使 .gitignore 忽略除少数文件之外的所有内容【英文标题】:Make .gitignore ignore everything except a few files 【发布时间】:2010-11-02 11:53:52 【问题描述】:

我了解 .gitignore 文件会掩盖 Git 版本中的指定文件 控制。我有一个项目 (LaTeX) 会生成大量额外文件 (.auth, .dvi、.pdf、日志等),但我不希望这些被跟踪。

我知道我可以(也许应该)这样做,所以所有这些文件都放在一个 项目中的单独子文件夹,因为我可以忽略该文件夹。

但是,是否有任何可行的方法可以将输出文件保存在 项目树并使用 .gitignore 忽略除我的文件之外的所有内容 用 Git 跟踪?类似的东西

# Ignore everything
*

# But not these files...
script.pl
template.latex
# etc...

【问题讨论】:

***.com/q/9162919/321973 的副本(我知道那是较新的,但那里的答案更正确)。其实this answer 可能是最好的 【参考方案1】:

我知道我迟到了,但这是我的答案。

正如@Joakim 所说,要忽略文件,您可以使用以下内容。

# Ignore everything
*

# But not these files...
!.gitignore
!someFile.txt

但如果文件在嵌套目录中,手动编写规则有点困难。

例如,如果我们想跳过 git 项目中的所有文件,而不是位于 aDir/anotherDir/someOtherDir/aDir/bDir/cDir 中的 a.txt。 那么,我们的.gitignore就会是这样的

# Skip all files
*

# But not `aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt`
!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

上面给出的.gitignore文件将跳过除!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt之外的所有目录和文件

您可能已经注意到,很难定义这些规则。

为了解决这个问题,我创建了一个名为 git-do-not-ignore 的网络应用程序,它将为您生成规则。

演示

输入

aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

输出

!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

工具

https://theapache64.github.io/git-do-not-ignore/

谢谢。

【讨论】:

干得好,好工具!它为我节省了很多工作。【参考方案2】:

这里有很多复杂的答案... 这是一些我在上面看不到的非常简单的东西,并且在许多情况下都能很好地工作:

# ignore all files that have an extension
**/*.*

# except for these extensions
!**/*.extension1
!**/*.extension2

这不会忽略任何无扩展名文件,但如果您有一堆名称相同或相似的文件,您可以为这些文件添加排除项

**/EXTENSIONLESSFILETOIGNORE

【讨论】:

【参考方案3】:

这就是我保留文件夹结构而忽略其他所有内容的方式。您必须在每个目录(或 .gitkeep)中有一个 README.md 文件。

/data/*
!/data/README.md

!/data/input/
/data/input/*
!/data/input/README.md

!/data/output/
/data/output/*
!/data/output/README.md

【讨论】:

这就是我要找的。但这真的是允许一个文件在一个被忽略的嵌套目录中的最简单的方法吗?我的有好几层…… 我认为您只需要为该文件创建一个例外,并且必须遵循父目录。 不幸的是,我认为这是最简单的方法,是的,如果这样可以让事情变得更容易,必须遵循父目录。【参考方案4】:

我解决此问题的最简单方法是强制添加文件。即使它被掩埋或嵌套在 git 忽略的子目录树中,它也会在 git 中进行说明。

例如:

.gitignore 中排除 x64 文件夹:

x64/

但您想包含位于x64/Release/ 目录中的文件myFile.py。 然后你必须:

git add -f x64/Release/myFile.py

您可以对多个匹配模式的文件执行此操作,例如

git add -f x64/Release/myFile*.py

等等。

【讨论】:

【参考方案5】:

如果你想忽略一个目录的全部内容,除了其中的一个文件,你可以为文件路径中的每个目录编写一对规则。例如。 .gitignore 忽略 pippo 文件夹,pippo/pluto/paperino.xml 除外

pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml

请注意,如果您只是在上面写了:

pippo/*
!pippo/pluto/paperino.xml

它不起作用,因为中间的 pluto 文件夹对于 Git 不存在,所以 paperino.xml 找不到存在的地方。

【讨论】:

很好的答案,但是对于以后遇到此问题的任何人来说,值得注意的是foofoo/* 相同。为此,您需要使用foo/* 作为基本文件夹 @Mayank Pippo 在意大利语中是 Goofy,而 Paperino 是唐老鸭,而 Pluto 在英语中是一样的。在过去,它们曾经是一个非常常见的变量名三元组,用于编程示例。很高兴再次阅读它们.. :) 对我不起作用:node_modules/* !node_modules/bootstrap 您必须包含!.gitignore,否则这将不起作用。 .gitignore 文件也不会被 git 跟踪【参考方案6】:

遇到了与 OP 类似的问题,但 前 10 名赞成的答案都没有真正起作用。 我终于发现了以下内容

语法错误:

*
!bin/script.sh

正确的语法:

*
!bin
!bin/script.sh

来自gitignore man page的解释:

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

这意味着上面的“错误语法”是错误的,因为bin/script.sh 不能被重新包含,因为bin/ 被忽略了。就是这样。

扩展示例:

$树。

.
├── .gitignore
└── bin
    ├── ignore.txt
    └── sub
        └── folder
            └── path
                ├── other.sh
                └── script.sh

$ cat .gitignore

*
!.gitignore
!bin
!bin/sub
!bin/sub/folder
!bin/sub/folder/path
!bin/sub/folder/path/script.sh

$ git status --untracked-files --ignored

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        bin/sub/folder/path/script.sh

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)
        bin/ignore.txt
        bin/sub/folder/path/other.sh

nothing added to commit but untracked files present (use "git add" to track)

【讨论】:

【参考方案7】:

要点

# Ignore everything
*

# But not these files...
!script.pl
!template.latex

并且可能包括:

!.gitignore

参考

来自https://git-scm.com/docs/gitignore:

一个可选的前缀“!”否定模式;任何被先前模式排除的匹配文件都将再次包含在内。如果排除了该文件的父目录,则无法重新包含该文件。出于性能原因,Git 不会列出排除的目录,因此包含文件的任何模式都无效,无论它们是在哪里定义的。对于以文字“!”开头的模式,例如“\!important!.txt”,在第一个“!”前面放置一个反斜杠(“\”)。

...

排除除特定目录foo/bar 之外的所有内容的示例(注意/* - 没有斜线,通配符也将排除foo/bar 中的所有内容):

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar

【讨论】:

【参考方案8】:

我就是这样做的:

# Ignore everything
*

# Whitelist anything that's a directory
!*/

# Whitelist some files
!.gitignore

# Whitelist this folder and everything inside of it
!wordpress/wp-content/themes/my-theme/**

# Ignore this folder inside that folder
wordpress/wp-content/themes/my-theme/node_modules

# Ignore this file recursively
**/.DS_Store

使用 gig status -u 递归查看未跟踪目录中的单个文件 - 使用 git status 您只会看到文件夹,这可能会让您误以为其中的所有内容都已被跟踪

【讨论】:

非常感谢您提供有关 -u 参数的提示。我已经在使用 git status 并且无法理解忽略规则,因为我得到了错误的未跟踪文件夹和文件列表.. 【参考方案9】:

我似乎找到了其他人没有提到的对我有用的东西。

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# And if you want to include a sub-directory and all sub-directory and files under it, but not all sub-directories
!subdir/
!subdir/**/*

基本上,它似乎否定了一个子目录被忽略,你必须有两个条目,一个用于子目录本身!subdir/,然后另一个扩展到它下的所有文件和文件夹!subdir/**/*

【讨论】:

【参考方案10】:

在大多数情况下,您希望使用/* 而不是**/

使用* 是有效的,但它以递归方式工作。从那时起,它不会查看目录。人们建议再次使用!*/ 将目录列入白名单,但实际上最好使用/* 将***别的文件夹列入黑名单

# Blacklist files/folders in same directory as the .gitignore file
/*

# Whitelist some files
!.gitignore
!README.md

# Ignore all files named .DS_Store or ending with .log
**/.DS_Store
**.log

# Whitelist folder/a/b1/ and folder/a/b2/
# trailing "/" is optional for folders, may match file though.
# "/" is NOT optional when followed by a *
!folder/
folder/*
!folder/a/
folder/a/*
!folder/a/b1/
!folder/a/b2/
!folder/a/file.txt

# Adding to the above, this also works...
!/folder/a/deeply
/folder/a/deeply/*
!/folder/a/deeply/nested
/folder/a/deeply/nested/*
!/folder/a/deeply/nested/subfolder

上述代码将忽略除.gitignoreREADME.mdfolder/a/file.txtfolder/a/b1/folder/a/b2/ 以及最后两个文件夹中包含的所有文件之外的所有文件。 (并且 .DS_Store*.log 文件将在这些文件夹中被忽略。)

显然我可以这样做!/folder!/.gitignore 也是。

更多信息:http://git-scm.com/docs/gitignore

【讨论】:

非常聪明,谢谢。 IMO,对于包含规则最少的 WordPress 网站来说,这是最好的方法。此外,未经您的明确许可,不会删除或添加任何新插件、主题或 WP 更新。使用 GitHub Desktop 时,我发现 .DS_Store 文件不会被忽略,但通过命令行这不是问题。为了解决这个问题,我不得不将**/.DS_Store 移到所有其他规则之下。 我的内部语法高亮对你的帖子标题有奇怪的反应。 谢谢!您还可以将文件夹中的文件列入白名单.. !/some/folder/file.txt @dallin 没有区别。一个将文件夹列入白名单,另一个将文件夹的子文件夹列入白名单,它们的作用相同。唯一的问题是必须先将文件夹或文件的父级列入白名单,然后才能将其列入白名单,因此如果不先执行!/nested/!/nested,就不能先执行/* 然后!/nested/folder/*(或等效的!/nested/folder) ! (可能介于两者之间的/nested/*)。要记住的一个技巧是,如果您将深度嵌套的子文件夹列入白名单,则需要将每个子文件夹中的子文件夹一直涂黑,而这些黑名单将以“斜线星”结尾... 为什么 **/.DS_Store 有反斜杠,而 **.log 没有?【参考方案11】:

如果您需要忽略除少数文件和少数 root 文件夹之外的所有内容,则简单的解决方案:

/*
!.gitignore
!showMe.txt
!my_visible_dir

神奇之处在于/*(如上所述)它会忽略(根)文件夹中的所有内容,但不会递归。

【讨论】:

赞成:要添加目录,!directory/* 不像以前的许多示例那样工作。它必须是 !directory,末尾没有斜线或 *。 @FrankForte 你看到我例子的最后一行了吗,这和你说的有什么矛盾?【参考方案12】:

我尝试了上面给出的所有答案,但没有一个对我有用。在阅读了 gitignore 文档 (here) 之后,我发现如果您首先排除一个文件夹,则子文件夹中的文件名不会被索引。所以如果你之后使用感叹号来包含一个文件,它不会在索引中找到,因此不会被包含在你的 git 客户端中。

这就是找到解决方案的方法。我开始为我的文件夹树中的所有子文件夹添加例外以使其正常工作,这是一项艰巨的工作。之后我能够将详细配置压缩为下面的配置,这与文档有点相反..

工作.gitignore:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' subfolder
/Pro/3rdparty/*
!Pro/3rdparty/domain/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

结果我在我的 git 客户端中看到,只有 Pro/3rdparty/domain/modulename/ 文件夹中的两个文件正在为下一次提交暂存,而这正是我想要的。

如果您需要将同一文件夹的多个子文件夹列入白名单,请在排除语句下方将感叹号行分组,如下所示:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' & 'hosting' subfolders
/Pro/3rdparty/*
!Pro/3rdparty/domain/
!Pro/3rdparty/hosting/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

# Ignore the 'hosting' folder, except for the 'modulename' subfolder
Pro/3rdparty/hosting/*
!Pro/3rdparty/hosting/modulename/

否则它将无法按预期工作。

【讨论】:

终于找到了一个可行的答案。我想知道我什么时候才能理解 .gitignore 的实际工作原理【参考方案13】:

我搞定了

# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib

【讨论】:

【参考方案14】:

我对单个文件的否定也有一些问题。我能够提交它们,但我的 IDE (IntelliJ) 总是抱怨忽略的文件,这些文件被跟踪。

git ls-files -i --exclude-from .gitignore

显示了我以这种方式排除的两个文件:

public/
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

最后,这对我有用:

public/*
!public/typo3conf/
public/typo3conf/*
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

关键是文件夹的否定 typo3conf/ 首先。

此外,语句的顺序似乎无关紧要。相反,您需要明确否定所有子文件夹,然后才能否定其中的单个文件。

文件夹!public/typo3conf/ 和文件夹内容public/typo3conf/* 对于.gitignore 来说是两个不同的东西。

很棒的线程!这个问题困扰了我一段时间;)

【讨论】:

【参考方案15】:

我的子文件夹有问题。

不起作用:

/custom/*
!/custom/config/foo.yml.dist

作品:

/custom/config/*
!/custom/config/foo.yml.dist

【讨论】:

【参考方案16】:

到目前为止,没有什么对我有用,因为我试图从 lib 添加一个 jar。

这不起作用:

build/*
!build/libs/*
!build/libs/
!build/libs/myjarfile.jar 

这行得通:

build/*
!build/libs

【讨论】:

【参考方案17】:

一个可选前缀! 否定模式;排除的任何匹配文件 以前的模式将再次包含在内。如果否定模式匹配, 这将覆盖较低优先级的模式源。

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# ...even if they are in subdirectories
!*/

# if the files to be tracked are in subdirectories
!*/a/b/file1.txt
!*/a/b/c/*

【讨论】:

看起来这也“忽略”了子文件夹,这样在根目录以外的任何地方都不会找到任何名为“script.pl”的文件。我现在正在使用它(使用 *.pl)并且所有 *.pl 文件都被忽略,即使 .gitignore 文件下面的子目录中有很多文件 @PandaWood 这个问题是由here (***.com) 提出的。这是由第一个匹配所有内容(包括目录)的表达式引起的,您永远不会否定它。要修复,添加 (!*/),它匹配当前目录中的任何子目录(递归)。这无助于父级答案,即将特定文件列入白名单(如果它们位于子目录中,您可能需要手动指定完整路径,或使用特定于目录的 .gitignore 文件)。 我无法让它工作。我忽略了一个文件夹(例如wp/),但我不想忽略该文件夹深处的一些文件(例如wp/path/to/some/location/*)。我可以让它工作的唯一方法是做git add -f wp/path/to/some/location/* @trusktr 使用 simont 的 !*/ 异常 天哪,最后一条规则:!*/ 使我徒劳地试图纠缠.gitignore 文件的工作变得完全不同。非常感谢。【参考方案18】:

要从 .gitignore 中排除文件夹,可以执行以下操作。

!app/

app/*
!app/bower_components/

app/bower_components/*
!app/bower_components/highcharts/

这将忽略bower_components 中的所有文件/子文件夹,/highcharts 除外。

【讨论】:

【参考方案19】:

这对我有用,我只想向 repo 提交一个 Cordova 插件:

...
plugins/*
!plugins/cordova-plugin-app-customization

【讨论】:

【参考方案20】:

更具体一点:

示例:忽略 webroot/cache 中的所有内容 - 但保留 webroot/cache/.htaccess

注意cache 文件夹后面的斜线 (/):

失败

webroot/cache*
!webroot/cache/.htaccess

有效

webroot/cache/*
!webroot/cache/.htaccess

【讨论】:

如果您使用的是 VS Code,请注意不要在将其应用于带有 .gitkeep 的文件夹后误读文件颜色,因为文件夹名称会变成绿色,但 .gitkeep 文件会像所有文件一样变成灰色其他被忽略的文件; .gitkeep 看起来像是被忽略了,但您应该看到右侧有一个“U”,表明它已被检测到【参考方案21】:

类似的问题很多,所以我把我之前写的贴出来:

我让它在我的机器上工作的唯一方法就是这样做:

# Ignore all directories, and all sub-directories, and it's contents:
*/*

#Now ignore all files in the current directory 
#(This fails to ignore files without a ".", for example 
#'file.txt' works, but 
#'file' doesn't):
*.*

#Only Include these specific directories and subdirectories and files if you wish:
!wordpress/somefile.jpg
!wordpress/
!wordpress/*/
!wordpress/*/wp-content/
!wordpress/*/wp-content/themes/
!wordpress/*/wp-content/themes/*
!wordpress/*/wp-content/themes/*/*
!wordpress/*/wp-content/themes/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*/*

请注意,您必须如何明确允许要包含的每个级别的内容。因此,如果我在主题下有 5 个子目录,我仍然需要将其拼写出来。

这是来自@Yarin 的评论:https://***.com/a/5250314/1696153

这些是有用的主题:

How do negated patterns work in .gitignore? How do gitignore exclusion rules actually work?

我也试过了

*
*/*
**/**

**/wp-content/themes/**

/wp-content/themes/**/*

这些都不适合我。很多线索和错误!

【讨论】:

这是唯一可以排他地包含某些文件扩展名的方法。更好的是,它制作了很棒的 ASCII 艺术:gist.github.com/Wolfgange3311999/91c671f5e4d3c56cf5a1【参考方案22】:

我有来自 Bower 的 Jquery 和 Angular。 Bower 将它们安装在

/public_html/bower_components/jquery/dist/bunch-of-jquery-files
/public_html/bower_components/jquery/src/bunch-of-jquery-source-files
/public_html/bower_components/angular/angular-files

最小化的 jquery 位于 dist 目录中,而 angular 位于 angular 目录中。我只需要将最小化的文件提交到 github。对 .gitignore 进行了一些篡改,这就是我设法想到的......

/public_html/bower_components/jquery/*
!public_html/bower_components/jquery/dist
/public_html/bower_components/jquery/dist/*
!public_html/bower_components/jquery/dist/jquery.min.js
/public_html/bower_components/angular/*
!public_html/bower_components/angular/angular.min.js

希望有人会觉得这很有用。

【讨论】:

【参考方案23】:

要忽略目录中的某些文件,您必须按正确的顺序

例如,忽略文件夹“application”中除 index.php 和文件夹“config”之外的所有内容注意顺序

你必须先否定你想要的。

失败

application/*

!application/config/*

!application/index.php

有效

!application/config/*

!application/index.php

application/*

【讨论】:

错了。你在“忽略一切”之后否定。 不要被git status 愚弄,检查您对.gitignore 的更改是否按预期工作 如果git status 不会告诉您它正在查看什么以及忽略了什么,那么您如何知道这是否有效? @kris 先清除 git 缓存。首先执行“git rm --cached *”然后您可以执行“git add --all”然后“git status”将显示所有新的 gitignore 更改。 你也可以使用**【参考方案24】:

您可以使用git config status.showUntrackedFiles no,所有未跟踪的文件都将对您隐藏。详情请见man git-config

【讨论】:

如果您只想提交多个文件中的几个,这很棒!【参考方案25】:
# ignore these
*
# except foo
!foo

【讨论】:

以上是关于使 .gitignore 忽略除少数文件之外的所有内容的主要内容,如果未能解决你的问题,请参考以下文章

bigquery 按除少数之外的所有列分组

使用 :not(selector) 选择除少数之外的所有元素 [重复]

Angularjs:限制对除少数页面之外的所有页面的访问

git忽略除指定文件/指定后缀名文件外的文件

使用 Nginx 阻止除少数机器人之外的所有机器人

如何使 JFileChooser 显示除 .huff 文件之外的所有类型的文件 [重复]