在Git中忽略目录的Unignore子目录

Wil*_*Wil 82 git gitignore

假设我忽略了一个目录,但我想在其中取消签名特定的子目录.所以我有设置:

/uploads/
/uploads/rubbish/
/uploads/rubbish/stuff/KEEP_ME/
/uploads/foo/
/uploads/foo/bar/lose/
Run Code Online (Sandbox Code Playgroud)

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

/uploads/*
!/uploads/rubbish/stuff/KEEP_ME/
Run Code Online (Sandbox Code Playgroud)

但这不起作用,也不是同一主题的几种排列.

一个有用的是

/uploads/**/**/**/
!/uploads/rubbish/stuff/KEEP_ME/
Run Code Online (Sandbox Code Playgroud)

但这感觉有点限制和冗长?

Art*_*rov 106

根据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/*
Run Code Online (Sandbox Code Playgroud)

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

!/uploads/rubbish/stuff/keep/**/*
Run Code Online (Sandbox Code Playgroud)

  • 这种方法不起作用(从 gi​​t 2.25 开始——也许 git 中的某些内容发生了变化)。我在下面发布了 /sf/answers/4220190481/ 作为更正。 (2认同)

Kin*_*nch 30

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

git add --force uploads/rubbish/stuff/KEEP_ME/
Run Code Online (Sandbox Code Playgroud)

但是,"KEEP_ME"似乎是一个目录而git通常不喜欢空文件夹,因此如果文件夹为空,您应该添加"占位符" - 持有者文件

git add --force uploads/rubbish/stuff/KEEP_ME/.keep_me
Run Code Online (Sandbox Code Playgroud)

  • `git add --force` 是错误的解决方案。如果您移动目录或将文件移动到另一个目录,git 的跟踪将删除该文件,但不会将其添加到新位置,您必须再次执行“git add --force”。通过不忽略通用模式,git 将跟踪存储库中文件的移动。 (4认同)

use*_*691 10

作为最高投票答案提出的解决方案是不正确的,因此很容易证明。

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

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"
Run Code Online (Sandbox Code Playgroud)

现在取消忽略被忽略的东西的父目录,如上:

echo 'uploads/rubbish/stuff/KEEP_ME/' >> .gitignore
echo 'uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u
Run Code Online (Sandbox Code Playgroud)

显示没有未跟踪的文件。

为了让它工作,您需要忽略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
Run Code Online (Sandbox Code Playgroud)

这使:

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

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


Jos*_*der 6

Buo-Ren LinJohn的回答很有帮助,但我需要将两者结合起来。

当想要排除其他子文件夹以及上传中的文件时,我发现有必要在给定文件夹之前明确指定任意目录,同时排除文件夹和包含子文件夹

**/uploads/*
!**/uploads/rubbish/
!**/uploads/rubbish/*
Run Code Online (Sandbox Code Playgroud)

我还发现有必要明确重新包含子文件夹及其内容以显示文件夹和子文件夹中的两个项目。


小智 5

在排除使用通用排除项的所有文件夹时,是否试图弄清楚如何包含特定文件夹

**/build
Run Code Online (Sandbox Code Playgroud)

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

然后添加另一行以更正要包含的路径

!**/folder/build/* 
Run Code Online (Sandbox Code Playgroud)

留给我们一个读取的gitignore

**/build/* 
!**/folder/build/* 
Run Code Online (Sandbox Code Playgroud)