使.gitignore忽略除几个文件以外的所有内容。

2567
我了解一个.gitignore文件可以隐藏指定的文件,让Git不对它们进行版本控制。

我该如何告诉.gitignore忽略除了我正在用Git跟踪的文件之外的全部文件呢?类似这样:

# Ignore everything:
*

# Do not ignore these files:
script.pl
template.latex

19
这是需要翻译的内容:Duplicate of https://dev59.com/bGox5IYBdhLWcg3wf0fl (I know that's newer, but the answer there is more correct). Actually this answer is probably the best。这句话的意思是:这是一个重复的问题,链接为https://dev59.com/bGox5IYBdhLWcg3wf0fl(我知道那个更新,但那里的答案更正确)。实际上,[这个答案](https://dev59.com/tmsz5IYBdhLWcg3wQFYq#8025106)可能是最好的答案。 - Tobias Kienzler
30个回答

3465

可选的前缀!表示否定该模式;任何被之前的模式匹配排除的文件将再次被包括。如果一个否定的模式匹配,它将覆盖优先级较低的模式。

# 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/*

26
看起来这个规则也会"忽略"子文件夹,所以除了根目录下的任何名为'script.pl'的文件以外,在其他地方的'script.pl'文件都找不到。我现在正在使用这个规则(使用*.pl),即使在.gitignore文件下面的许多子文件夹中有很多*.pl文件,它们也都被忽略了。 - PandaWood
52
@PandaWood 这个问题在这里被提出来了(stackoverflow.com)。它是由第一个表达式匹配所有内容,包括目录,而你从未否定它所造成的。要解决这个问题,需要添加(!*/),它将匹配当前目录中的任何子目录(递归)。这并不能帮助原始问题的解答,因为它是白名单特定文件(如果它们在子目录中,您可能需要手动指定完整路径或使用特定于目录的.gitignore文件)。 - simont
56
我无法让这个工作。我正在忽略一个文件夹(例如,wp/),但我想不忽略那个文件夹深处的一些文件(例如,wp/path/to/some/location/*)。我唯一能让它工作的方法是执行 git add -f wp/path/to/some/location/* - trusktr
18
@trusktr 使用 Simont 的 !*/ 异常。 - Tobias Kienzler
10
天啊,最后那个规则:!*/ 在我的无效尝试中对让 .gitignore 文件起作用发挥了关键性作用。非常感谢你。 - racl101
显示剩余15条评论

1048

如果您想忽略一个目录的所有内容,除了其中一个文件之外,您可以在文件路径中为每个目录编写一对规则。例如,.gitignore可以忽略pippo文件夹,但不包括pippo/pluto/paperino.xml

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

请注意,文件夹需要使用/*进行标记。以下内容将无效:
folder
!folder/some-file.txt

但只有这个会:
folder/*
!folder/some-file.txt

请注意,如果你只是简单地在上面写了这句话:
pippo/*
!pippo/pluto/paperino.xml

这样做行不通,因为中间的“pluto”文件夹对于Git来说是不存在的,所以“paperino.xml”无法找到一个存在的位置。

105
非常好的回答,但值得注意的是,任何以后遇到这个问题的人需要知道 foofoo/* 不是同一个东西。为了让这个方法起作用,你 必须 使用 foo/* 作为基础文件夹。 - thislooksfun
46
在意大利语中,皮波是高飞,而唐老鸭则是唐老鸭,而冥王星与英语中的名称相同。它们曾经是编程示例中常见的三元组变量名。很高兴再次读到它们。 :) - Ghidello
10
对我来说不起作用。node_modules/* !node_modules/bootstrap - SuperUberDuper
2
你必须包含.gitignore文件,否则这将无法工作。 .gitignore文件也将被Git忽略。 - suhailvs
2
@simple_human 如果他忽略了存储库根目录中的所有内容,或者他有一个关于在提到的目录内的.gitignore文件需要注意,那么这将是正确的。 - xZero
显示剩余9条评论

378

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

使用*是有效的,但它会递归地工作。它不会再查看目录。人们建议使用!*/再次包含列表目录,但实际上最好使用/*阻止最高级文件夹。

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

# Includelist some files
!.gitignore
!README.md

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

# Includelist 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


5
非常聪明,谢谢。在我看来,这是处理 WordPress 网站的最佳方式,包含规则的数量最少。此外,任何新的插件、主题或 WP 更新都不会在未经您明确许可的情况下被删除或添加。当使用 GitHub Desktop 时,我发现 .DS_Store 文件不会被忽略,但通过命令行就不会出现这个问题。为了解决这个问题,我必须将 **/.DS_Store 移到所有其他规则之下。 - Jibran
10
我的内在语法高亮器对你的帖子标题有一种奇怪的反应。 - itsadok
3
谢谢!您也可以将文件夹中的文件加入白名单。!/some/folder/file.txt - PodTech.io
2
@dallin 没有区别。一个白名单文件夹,另一个白名单该文件夹的子项,这两者是相同的。唯一的问题是必须先将文件夹或文件的父级列入白名单,然后才能将其列入白名单,因此您不能在不先执行 !/nested/!/nested 的情况下执行 /* 然后执行 !/nested/folder/*(或等效的 !/nested/folder)!一个记忆技巧是,如果您要将深度嵌套的子文件夹列入白名单,则需要在每个子文件夹中黑名单其子项,一直到最上层,而这些黑名单将以“斜杠星号”结尾... - Ryan Taylor
1
@RyanTaylor 我一直在寻找一个解决方案,可以在开发环境中将我们所使用的平台的模块保存在 git 中,并且这个方法非常完美,我简直不敢相信。非常感谢你! - Kellen Murphy
显示剩余6条评论

103

稍微具体一些:

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

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

失败了

webroot/cache*
!webroot/cache/.htaccess

工作

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

如果您正在使用VS Code,请注意,将此应用于带有.gitkeep的文件夹后不要误读文件着色,因为文件夹名称将变为绿色,但.gitkeep文件将像所有其他被忽略的文件一样变为灰色。.gitkeep看起来像是被忽略了,但您应该看到右侧有一个“U”,表示已检测到它。 - OzzyTheGiant

89

让我们工具化吧!

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

# Ignore everything
*

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

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

例如,如果我们想要跳过除 a.txt 之外的所有文件,它们位于 aDir/anotherDir/someOtherDir/aDir/bDir/cDir 中。 那么,我们的 .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

这很难手写。

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

工具

演示

示例输入

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

1
很棒的工具,但是在处理文件夹时会出现问题。当处理文件夹时,需要删除倒数第二行。顺便说一句,如果将其作为vscode扩展添加,您将获得大量下载量。祝好! - titusfx
1
太棒了!救了我的一天!! - undefined
这在我看来是正确的解决方案。而且它还是开源的!https://github.com/theapache64/git-do-not-ignore/tree/master - undefined

88
# ignore these
*
# except foo
!foo

42

我有与楼主类似的问题,但是前十个受欢迎的回答都实际上都没有起作用
最终我找到了以下解决方法:

错误的语法:

*
!bin/script.sh

正确的语法:

*
!bin
!bin/script.sh

来自gitignore手册的解释:

一个可选的前缀“!”表示否定该模式;任何被前面的模式排除的匹配文件将重新包含。如果排除了该文件所在的父目录,则不可能重新包含该文件。Git出于性能原因不会列出已排除的目录,因此对包含文件的任何模式都没有影响,无论它们在何处定义。

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

扩展示例:

$ tree .

.
├── .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)

谢谢,这应该是被采纳的答案!比其他帖子更漂亮、更易读。 - Kheldar
只有一个答案有效;人们热议的 !*/ 模式似乎重新包含了我试图排除的所有那些文件夹。但是我怀疑这个解决方案在需要排除大量文件/子文件夹时并不理想。 - Hans

36
为了忽略目录中的某些文件,必须按照正确的顺序进行操作:
例如,忽略"application"文件夹中的所有内容,除了index.php和"config"文件夹注意顺序
您必须先否定您想要的内容。 错误做法: application/* !application/config/* !application/index.php 正确做法: !application/config/* !application/index.php application/*

45
错误。在“忽略一切”之后执行否定操作。 - Carlos Melo
3
不要被git status骗了,以此来检查你对.gitignore的更改是否按预期生效。 - Philippe Rathé
14
如果git status不能告诉你它正在查看什么以及忽略了什么内容,那么你如何知道这个功能是否有效? - kris
1
@kris 首先清除 git 缓存。首先执行 "git rm --cached *",然后可以执行 "git add --all",接着执行 "git status" 将显示所有新的 gitignore 更改。 - Mark McCorkle
你可以使用 **。 - Nick Turner

25
您可以使用git config status.showUntrackedFiles no命令,它会将所有未跟踪的文件隐藏起来。详见man git-config了解更多细节信息。

1
如果你只想提交少量文件,这非常棒! - Josh M.

24

这就是我保持文件夹结构的方法,同时忽略其他所有内容。你必须在每个目录中有一个README.md文件(或.gitkeep)。

/data/*
!/data/README.md

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

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

这正是我在寻找的。但这真的是允许一个被忽略的嵌套目录中的一个文件的最简单方法吗?我的目录有好几层深... - Fred
1
我认为你只需要为这个文件和父目录创建一个异常。 - Miladiouss
1
不幸的是,我认为这是最简单的方法,是的,如果父目录跟随的话会更容易些。 - Miladiouss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接