我有以下文件夹结构:
/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
有人可以解释,为什么会这样?有没有更简洁的方法呢?
答案 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}})。
解决此问题的一种方法是执行以下操作:
.gitignore
:data/**
!data/**/
!data/**/.gitkeep
git add data
从.gitignore中删除第二行:
data/**
# !data/**/
!data/**/.gitkeep
git add .gitignore
git commit
这会将数据目录结构提交给git,并确保将来进行的任何git
调用都将完全忽略数据子目录的内容。