忽略Git中被忽略目录的子目录


99

假设我已经忽略了目录,但是我想忽略其中的特定子目录。所以我有设置:

/uploads/
/uploads/rubbish/
/uploads/rubbish/stuff/KEEP_ME/
/uploads/foo/
/uploads/foo/bar/lose/

我想忽略除KEEP_ME目录之外的所有内容。我希望忽略将看起来像:

/uploads/*
!/uploads/rubbish/stuff/KEEP_ME/

但这是行不通的,并且在同一主题上也没有几个排列。

起作用的是

/uploads/**/**/**/
!/uploads/rubbish/stuff/KEEP_ME/

但这有点限制性和冗长吗?


1
您提供的代码对我不起作用(使用git版本1.9.1)。起作用的一个是/ uploads / *!/ uploads / rubbish / / uploads / rubbish / *!/ uploads / rubbish / stuff / uploads / rubbish / stuff / *!/ uploads / rubbish / stuff / keep(类似于示例在git-scm.com/docs/gitignore中)。我的文件夹结构;└README.md└uploads / foo / bar / lose / lose.txt└uploads / rubbish / stuff / keep / keep.txt
gihanchanuka 2014年

Answers:


119

根据gitignore文档的模式格式部分

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

因此,在排除其父目录/uploads/rubbish/stuff/keep/模式的内容之前,必须对其进行排他性的排除:

#ignore everything within /uploads/ 
/uploads/*

#include everything within /uploads/rubbish/stuff/keep
!/uploads/rubbish/stuff/keep/  
!/uploads/rubbish/stuff/keep/*

要在其中包含子目录,请/uploads/rubbish/stuff/keep/添加第三行:

!/uploads/rubbish/stuff/keep/**/*

1
您使用的是哪个版本的git?也许这仅在某些版本中可用。

尴尬。我忘了发表此评论。不过,我知道了。FWIW,我不使用斜杠。我不记得这是否是问题。我正在使用1.7.2.5。

我有一个全局gitignore文件,其中忽略了所有* .zip文件。但是对于特定项目,我想包含zip文件。我将此行添加到该项目中.gitignore,并且效果很好!:!*.zip
Jinghao Shi

我发现有必要在给定文件夹之前和之后显式指定任意目录,同时排除文件夹和包括子文件夹。(完整答案)。
乔西亚·尤德

此方法不起作用(从git 2.25开始-可能git中的某些内容已更改)。我在下面发布了stackoverflow.com/a/60288435/295691作为更正。
user295691

34

即使您向中添加了一些内容.gitignore,也可以强制 git将其添加到索引中

git add --force uploads/rubbish/stuff/KEEP_ME/

但是,“ KEEP_ME”似乎是一个目录,而git通常不喜欢空文件夹,因此,如果该文件夹为空,则应该添加一个“占位符” -holder文件

git add --force uploads/rubbish/stuff/KEEP_ME/.keep_me

唯一的问题是,这个特定示例引用了我应该提到的全局gitignore。我知道我可以强制添加项目,但是如果添加了任何新项目,以及每个新存储库最初都必须添加新项目。.keep是否确保不忽略内容?
维尔

1
做一点测试。是的,您必须使用git add --force中的每个新项目或文件夹KEEP_ME。但是在那之后,就像git add -u文件被“忽略”一样,只是添加了更新(例如,执行a时)。在.keep_me使GIT中的文件夹上运行什么都不做,它只是一个文件。
commonpike 2015年

1
git add --force这是错误的解决方案。如果您在某个目录中移动或将文件移动到另一个目录,则git的跟踪将删除该文件,但不会将其添加到新位置,因此您必须git add --force再次进行操作。通过忽略通用模式,git将跟踪存储库中文件的移动。
Merlin

这是唯一对我有用的解决方案。我的文件夹未被忽略,但是我无法以任何方式添加它。这种方式为我解决了。
秋藤

6

试图找出使用通用排除排除所有文件夹时如何包括特定文件夹

**/build

如果/*在通用排除的末尾添加,则继续排除所有构建文件**/build/*

然后添加另一行以更正要包含的路径,使其看起来像

!**/folder/build/* 

给我们留下一个读着的gitignore

**/build/* 
!**/folder/build/* 

2

林布仁约翰的答案很有帮助,但我需要将两者结合起来。

当要排除其他子文件夹以及上载中的文件时,我发现有必要在给定文件夹之前显式指定任意目录,同时排除文件夹和包括子文件夹

**/uploads/*
!**/uploads/rubbish/
!**/uploads/rubbish/*

我还发现有必要显式重新包括子文件夹及其内容,以显示文件夹和子文件夹中的项目。


叹。零运气在这里。现在已经几个小时了。Git 2.20.1
RichieHH

@HörmannHH很抱歉听到这个消息。也许是时候问一个新问题了吗?
Josiah Yoder

2

提出最多的答案的解决方案是不正确的,因此很容易证明。

首先忽略上载/ *中的所有内容:

mkdir -p uploads/rubbish/stuff/KEEP_ME
touch uploads/a uploads/rubbish/a uploads/rubbish/stuff/a uploads/rubbish/stuff/KEEP_ME/a
echo '/uploads/*' >> .gitignore
git init
git add .
git commit -m "Initial commit"

现在,如上所述,忽略忽略的内容的父目录:

echo 'uploads/rubbish/stuff/KEEP_ME/' >> .gitignore
echo 'uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

不显示未跟踪的文件。

为了使其正常工作,您需要忽略uploads/树下的所有文件(uploads/**/*,而不仅仅是顶层文件uploads/*),然后添加要保留的树的所有父目录

echo '/uploads/**/*' > .gitignore
echo '!/uploads/rubbish/' >> .gitignore
echo '!/uploads/rubbish/stuff' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

这使:

On branch master
...
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        uploads/rubbish/stuff/KEEP_ME/a

如果我们uploads/*.gitignore上面使用过,那么所有中间文件也将包括在内,因此例如uploads/rubbish/a将显示在上面的status命令中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.