gitignore文件夹中的所有文件但保留文件夹结构

时间:2017-09-19 13:30:07

标签: git gitignore

我有以下文件夹结构:

/foo/
/foo/test.txt
/foo/.gitkeep
/foo/bar/test.txt
/foo/bar/.gitkeep
/foo/bar/baz/test.txt
/foo/bar/baz/.gitkeep

现在我要排除文件夹中的所有文件" foo"以及其子文件夹(和子文件夹)中的所有文件,除了所有.gitkeeps(以便保留文件夹结构)。这也适用于3个以上级别的子文件夹。

以下gitignore规则有效:

/foo/**
!/foo/**/
!/foo/**/.gitkeep

有人可以解释,为什么会这样?有没有更简洁的方法呢?

3 个答案:

答案 0 :(得分:6)

规则很简单:

It is not possible to re-include a file if a parent directory of that file is excluded.

这就是你需要的原因

  • 递归忽略文件和文件夹:

    /foo/**
    

(如果您只忽略/foo/,即文件夹,那么!排除规则就不会有效,因为foo/文件夹本身被忽略了:Git会在那里停止)

  • 然后从忽略规则中排除文件夹:

    !/foo/**/
    
  • 之前.gitkeep

    等文件列入白名单
    !/foo/**/.gitkeep
    

这是有效的,因为.gitkeep父文件夹被排除在忽略规则之外。

与贝尔纳多原始提案(before his edit)相反:

/foo/** 
!**/.gitkeep

如果不排除/**忽略规则中的文件夹,则文件的排除规则不起作用。

您可以通过以下方式检查:

git check-ignore -v -- /path/to/.gitkeep

scm .gitignore中所述:

  • 使用' *'与' **'
  • 相同
  • 使用!.gitkeep(不带任何/锚)会递归地排除该文件。

在这两种情况下,' recursively'是解释为什么可以应用排除规则的关键术语:如果您忽略文件夹(例如./foo/),您将无法排除该文件夹中的任何内容。
但是如果忽略元素(文件和文件夹)递归***),从gitignore规则中排除文件夹(再次通过递归规则) !*),然后您可以排除(白名单)文件。

答案 1 :(得分:2)

我已经完成了。似乎需要的是所需文件夹中的.gitignore文件。

查看this repository,它完全符合您的要求。

我尝试在foo/foo/bar/foo/bar/baz/中添加任何文件名,但它只接受.gitkeep。

诀窍是使用此内容创建一个.gitignore,在文件夹中:

*
!*/
!.gitignore
!.gitkeep

[编辑:根据评论添加]

你应该能够缩短到:

*
!*/
!.git*

虽然将来可能不太清楚是什么意思。

虽然此解决方案不会缩短原始.gitignore所需的行数,但这确实还有其他一些优势 - 主要原因是这将是.gitignore个文件在文件夹中,这意味着它可以是只有这些行的干净文件,并且仅适用于此文件夹。

这意味着可以将此.gitignore文件轻松移动到需要此过滤器的任何特定文件夹中。此外,整个文件夹可以在仓库中轻松移动,甚至可以移动到不同的仓库,而无需修改.gitignore。它更清晰,更易于维护,并且不会隐藏在repo的根文件夹中通常较大的.gitignore文件中。

答案 2 :(得分:0)

我没有足够的声誉来发表评论,但是我想提出一个重要的问题:

  • 在安装了数据文件夹的情况下,这会导致 git 命令(例如git status)运行非常慢,因为这些命令仍会扫描所有文件(尽管不提交它们),它将通过网络缓慢运行。

  • 更不可预测的是,这会导致 Oh My Zsh (如果已安装)在每个命令之后挂起外壳一段时间,因为它会静默地检查git分支(我提出了{ 3}})。

解决此问题的一种方法是执行以下操作:

  1. 将此添加到您的.gitignore
data/**
!data/**/
!data/**/.gitkeep
  1. git add data

  2. 从.gitignore中删除第二行:

data/**
# !data/**/
!data/**/.gitkeep
  1. git add .gitignore

  2. git commit

这会将数据目录结构提交给git,并确保将来进行的任何git调用都将完全忽略数据子目录的内容。