当某些中间目录名称看起来像文件名时,如何递归地从 git 中排除除具有特定扩展名的文件之外的所有内容?

How to exclude from git everything except files with specific extension, recursively when some intermediary dir names look like file names?

我试图从 git 存储库中排除除 .asd 文件之外的所有内容。这些文件可能位于目录层次结构的任何级别,任何级别的任何目录的名称中可能包含也可能不包含点,使它们看起来像文件名。

例如:

设置存储库和一些目录结构:

$ mkdir repository && cd repository && git init && touch .gitignore
$ mkdir -p foo/fooo/foooo/fooooo.srcs/fooooo bar/barr.srcs/barr/barrr foo/fooo/foooo/fooooo.cache/fooooo

在我们想要包含的树中的不同级别添加一些 .asd 文件:

$ touch foo/file1.asd foo/fooo/foooo/fooooo.srcs/file2.asd bar/barr.srcs/file3.asd bar/barr.srcs/barr/barrr/file4.asd foo/fooo/file5.asd

托管存储库的父目录的大部分内容都是随机的。这些东西可能是各种未知类型的文件等,因此专门声明应忽略的所有内容是不可取的。声明我们想要包含的内容更容易(或者应该更容易)。添加一些随机的东西:

$ touch huge.pdf asd.yo foo/fooo/foooo/fooooo.cache/foo.txt foo/fooo/foooo/fooooo.cache/fooooo/asd.sh bar/intro.pptx

带空.git忽略,全部包含:

$ git status -u -s
?? .gitignore
?? asd.yo
?? bar/barr.srcs/barr/barrr/file4.asd
?? bar/barr.srcs/file3.asd
?? bar/intro.pptx
?? foo/file1.asd
?? foo/fooo/file5.asd
?? foo/fooo/foooo/fooooo.cache/foo.txt
?? foo/fooo/foooo/fooooo.cache/fooooo/asd.sh
?? foo/fooo/foooo/fooooo.srcs/file2.asd
?? huge.pdf

我试过以下 .gitignore:

*.*
!*/**/*.asd

仅包括 file1.asdfile5.asd,缺少其他 3 个 .asd 文件,这些文件位于某些名称中包含点的目录中。尝试专门添加其中之一会揭示问题:

$ git add foo/fooo/foooo/fooooo.srcs/file2.asd
The following paths are ignored by one of your .gitignore files:
foo/fooo/foooo/fooooo.srcs
Use -f if you really want to add them.

那么在这种存储库结构中是否甚至可以仅使用 .gitignore 来查看 .asd 文件?毕竟这里追求的东西更多的是我猜不存在的“.gitinclude”东西。当然,我可以忘记尝试在 .gitignore 中定义相关的 git 范围,而只是使用 git add *.asd 代替 git add . 但这不是很好。例如。 VS Code 的 git 扩展仍然过于丰富多彩,因为它也考虑了 git 范围内的所有不相关文件。

要击败 Git 的 .gitignore 目录优化,请使用:

!*/

在这种情况下,您最终会得到这个 .gitignore 文件:

*
!*/
!*.asd

请注意,这意味着每个 git status 都会搜索您的工作树中的每个目录,无论最终是否毫无意义。所以它有点 CPU-昂贵 — 但它会解决这个特定问题。