如何将空目录添加到Git存储库?


4260

如何将空目录(不包含文件)添加到Git存储库?


16
尽管它没有用,但是有一种方法可以将空目录(真正是空目录)入侵到您的repo中。但是,它不会checkout与当前版本的Git一起使用。
tiwo 2012年

335
@tiwo我不同意它没有用。目录层次结构是项目的一部分,因此应进行版本控制。
JBentley 2013年

114
就我而言,我想为tmp文件添加目录结构,而不是tmp文件本身。通过这样做,我的测试器具有正确的结构(否则会有错误),但是我不会用tmp数据阻塞我的提交。是的,对我有用!
亚当·马歇尔

45
@AdamMarshall我认为tiwo在说该hack没有用,因为它被结帐忽略。Tmp目录确实听起来像是VCS的有用功能。
Quantum13年

31
为什么没有创建tmp文件的过程也创建tmp目录?
RyPeck

Answers:


4124

使目录保持(在存储库中)几乎为空的另一种方法是.gitignore在该目录内创建一个包含以下四行的文件:

# Ignore everything in this directory
*
# Except this file
!.gitignore

这样,您就不必像m104 解决方案中那样正确地获得订单。

这也带来了好处,当您执行git状态时,该目录中的文件不会显示为“未跟踪”。

使@GreenAsJade的评论持续存在:

我认为值得一提的是,该解决方案恰好满足了该问题的要求,但也许并不是许多关注此问题的人一直在寻找。此解决方案确保目录保持为空。它说:“我真的不希望在这里签入文件”。与“我还没有任何文件可以在这里签入,但是我需要在这里的目录,文件可能稍后再来”相反。


25
我认为@JohnMee提出的README解决方案应与此一起使用;.gitignore文件提供了对我们希望不受版本控制的限制的解释,而README文件则解释了目录的用途,它们都是非常重要的信息。
pedromanoel 2013年

18
@pedromanoel我写了您将放在文件README内部的.gitignore文档(作为注释)。
卡洛斯·坎德罗斯(CarlosCampderrós)

69
找出1个区别:1.)一个空文件夹,2.)其中带有.gitignore文件的文件夹。;-)
PeterPerháč2014年

6
这非常适合 缓存文件夹。
2014年

10
不幸的是,这导致了一个非空目录,它只有一个隐藏文件。
佩多罗

1090

你不能 请参阅Git常见问题解答

当前,git索引(临时区域)的设计仅允许列出文件,并且没有足够的能力来进行更改以允许空目录的人对此情况已经足够在意,以进行补救。

在目录中添加文件时会自动添加目录。也就是说,目录永远不必添加到存储库,也不需要单独跟踪。

您可以说“ git add <dir>”,它将在其中添加文件。

如果您确实需要在结帐中存在目录,则应在其中创建一个文件。.gitignore为此很好地工作;您可以将其保留为空,或填写您希望在目录中显示的文件名。


67
下面的答案要好得多。git低级软件不允许使用的事实对我来说并不重要,而当我需要一个空目录时,如何实际使用Git并不重要。添加2行.gitignore对我来说似乎可以接受。
阿马拉

1
好吧,如果您想将文件移动到新目录中,则无法完成,git mv因为git会抱怨新目录不受版本控制
lulalala 2011年

16
对于这个常见问题,您可以在Internet上阅读“ 不可能,不能等等 ”。该.gitignore技巧是一个常见的回答,满足多种需求。但是有可能使git跟踪一个真正的空目录,请参阅我的答案
ofavre 2012年

2
尽管我想得越多,但感觉像“空字符串的SHA哈希”越多,如果存在,实际上是一个空树的定义明确的标识符,除非无法分辨该对象是否是一棵树或斑点。
Emil Lundberg

21
我已经看到了很多.gitkeep为此目的而使用称为空文件的存储库。
Sukima

759

.gitkeep在目录中创建一个名为的空文件,然后添加它。


58
我添加了一个鼓励创建答案的答案.keep
Acumenus 2014年

205
.gitkeep尚未由Git规定,并将让人们第二次猜测其含义,这将导致他们进入google搜索,这将导致他们进入此处。该.git前缀约定应为文件和目录保留了Git本身使用。
t-mart 2014年

10
@ t-mart“ .git前缀约定应该保留...”为什么?git是否要求此保留?
有限赎罪

9
在这种情况下,一个READMEABOUT文件将是一样好或更好。给下一个家伙留下笔记,就像我们以前都在URL之前一样。
戴夫

5
如果您要编写应该在空目录上测试代码的单元测试,则无法使用...
thebjorn 2015年

435

您总是可以将README文件放在目录中,并说明为什么要在存储库中使用此目录(否则为空)。


39
+1,一个好的建议,一个空目录没有任何意义,除非将来要使用它。因此,在其中创建一个README文件,并写出该目录的作用,以及将来将放置哪些文件。这解决了两个问题。
saeedgnu 2011年

63
@ilius废话。在许多情况下,非常需要包含空目录的目录结构(例如,您需要模型目录但还没有创建任何模型的MVC应用,或者稍后打算向其中添加共享视图的共享视图目录) )。此外,将README放在其中的每一个中都是过大的,因为很明显它们的用途,并且很容易忘记在其中的每一个中都放入README。并且,当您向其中添加一些其他文件时,您必须记住删除自述文件。基本上,git应该绝对允许空目录。
Jez 2012年

20
@Jez:我不同意。关键是git被设计为控制(和索引)源代码。重要的是,提交的ID是内容的哈希。也就是说,它必须具有内容。您不需要树的每个部分都有自述文件,只需要叶节点即可。如果您有放置代码的地方,但没有代码,甚至没有时间回显“模型的地方” >>自述文件,那么您所拥有的就是一个想法,而不是提交。git没有兴趣。说“我希望正在运行的应用程序具有XYZ空目录”是一个运行时问题,而不是源问题。使用安装程序进行处理。
2013年

6
@JoeAtzberger这是一项缺少的功能,不是故意的限制。来自Git常见问题解答:当前,Git索引(暂存区)的设计仅允许列出文件,没有人有足够的能力进行更改以允许空目录对这种情况进行了足够的补救。
jbo5112 2013年

7
@ jbo5112是的,您引用的“特殊代码”是我提到的“安装程序”。您的webapp安装已经必须处理创建数据库,本地配置,提取依赖项或其他100项操作,但是还有几个空目录吗?尝试gradle,passenger,chef,primitive的Makefile等。在创建目录和安装应用程序的其他工作(可能会更复杂/更危险)之间没有安全性区别。而且,如果您确实没有dep,config,DB等,也没有安装程序,则只需使用README。没有任何情况要求您同时进行。
Joe Atzberger 2013年

348
touch .keep

在Linux上,这将创建一个名为的空文件.keep。就其价值而言,此名称与Git无关,而与Git无关.gitkeep。其次,正如另一个用户所指出的,.git前缀约定应该保留给Git本身使用的文件和目录。

或者,如另一个答案中所述,目录可以包含描述性文件READMEREADME.md文件

当然,这要求文件的存在不会导致应用程序中断。


1
这对于初始的裸目录很有用,但是如果它开始填充文件怎么办?然后,Git将注意到它们并将它们声明为未跟踪文件。此处选择的答案的工作方式更为优雅,可以保留目录,但可以安全地忽略目录。
JakeGould 2014年

14
问题和主要的普遍关注是关于添加一个空目录。如果以后有驻留文件,则显然删除该.keep文件或不理会它。如果要忽略目录中的文件,则完全是另一个问题。
Acumenus

3
建议git clean -nd | sed s/'^Would remove '// | xargs -I{} touch "{}.keep"在所有未跟踪的空目录中执行此操作。
Acumenus 2014年

1
不喜欢这种解决方案,很难猜测此文件的作用。另外,如果您是在开发环境中生成文件(如日志或图像等),则不会阻止对这些文件进行版本控制并进入生产环境,这不是很好。
danielrvt '16

1
Windows不喜欢没有名称的文件,并且需要特殊的技巧来完成此操作(又称bash式终端应用程序或等效程序)。
EntangledLoops

303

为什么我们需要空的版本文件夹

首先要注意的是:

空目录 在Git版本控制系统下,不能成为树的一部分

它根本不会被跟踪。但是在某些情况下,“版本化”空目录可能很有意义,例如:

  • 脚手架一个预先定义的文件夹结构,使其可用于存储库的每个用户/贡献者; 或者,作为上述的一种特殊情况,为我们要提供文件夹但其内容的临时文件(如cache/logs/目录)创建一个文件夹.gitignore
  • 与上述有关的一些项目 如果没有某些文件夹将无法工作(这通常是项目设计不佳的暗示,但这是一个经常在现实世界中出现的场景,也许可能会解决权限问题)。

一些建议的解决方法

许多用户建议:

  1. 放置一个 README文件或其他文件放入某些内容,以使目录为非空目录,或者
  2. 创建.gitignore具有某种“反向逻辑”(即包括所有文件)的文件,最后,该文件具有与方法1相同的目的。

虽然这两种解决方案都能正常工作,但我发现它们与有意义的Git版本控制方法不一致。

  • 为什么要在项目中放入您可能不需要的伪造文件或自述文件?
  • 即使有可能,为什么要使用.gitignore做某事(保留文件)与本意相反(不包括文件)呢?

.gitkeep方法

使用一个文件名为.gitkeep,以强制在版本控制系统中存在该文件夹。

尽管看起来差别不大:

  • 您使用具有单个保持文件夹的目的。您不会在此处放置任何您不想放置的信息。

    例如,您应该使用自述文件以及具有有用信息的自述文件,而不是保留文件夹的借口。

    关注点分离始终是一件好事,您仍然可以添加.gitignore忽略不必要的文件。

  • .gitkeep从文件名本身(以及其他开发人员,这对于共享项目和Git存储库的核心目的之一而言),从文件名本身起,它的名称变得非常清楚和直接。

    • 与代码无关的文件(由于前导点和名称)
    • 与Git明确相关的文件
    • 它的目的(keep)清楚地说明了,并且在含义上是一致的并且在语义上是对立的,可以忽略

采用

我已经看到了.gitkeep非常重要的框架(例如LaravelAngular-CLI)采用的方法。


8
您错过了一个想法-保留和清空文件夹的原因是什么(例如/ logs,/ tmp,/ uploads)?是的-它可以使文件夹为空。:)因此,如果要将文件夹保留为空,则必须忽略其中的文件。
罗马

14
@RomanAllenstein:不一定。可能是您创建了具有给定结构的存储库,以后可以填充该存储库。这些文件一经创建,便会立即添加到存储库中,开始删除或编辑.gitignore文件会很烦人(这很危险,因为您可能甚至没有意识到它们没有被跟踪:git忽略了它们。 )
blueFast 2015年

45
@Behnam:我会打倒票,但是我对SO元数据的研究并不关心冗长的答案,只要它们提供了足够的细节和清晰度以对每个读者(每个技能水平)都有用。我仍然对任何批评持开放态度,感谢您公开宣布理由,我非常肯定。
Cranio

4
如果您编辑答案以替换.gitkeep为任何其他非git前缀的文件名,您将得到我的认可,我认为这是最好,最有用的答案。原因:我认为应该为git规定的文件保留“ .git *”,但这只是一个占位符。我的第一个猜测是,例如,“。gitkeep”文件将被自动忽略(这将是一个不错的功能),但事实并非如此,对吧?
约翰尼

5
我不知道为什么人们很难理解为什么要向git添加“空”文件夹。您必须从某个地方开始,对不对?因此,通常您从项目文件夹结构开始-las-在项目开始时还没有任何东西。项目回购完成后,团队工作人员可以克隆并开始使用SAME结构。
BitTickler '18 -10-21

127

如其他答案所述,Git无法在其暂存区域中表示空目录。(请参阅Git常见问题解答。)但是,如果出于您的目的,如果目录.gitignore仅包含文件,则该目录足够空,则.gitignore只能通过以下方式在空目录中创建文件:

find . -type d -empty -exec touch {}/.gitignore \;

21
您可能要忽略.git目录: find . -name .git -prune -o -type d -empty -exec touch {}/.gitignore \;
steffen 2013年

3
在大多数情况下,更简单的变化是find * -type d -empty -exec touch {}/.gitignore \;
akhan

2
由于OS X几乎在每个目录中都创建一个.DS_Store文件,因此该功能在此无效。我发现的唯一(DANGEROUS!)解决方法是先通过删除所有.DS_Store文件find . -name .DS_Store -exec rm {} \;,然后使用此答案中的首选变体。确保仅在正确的文件夹中执行此操作!
zerweck

1
有谁知道在Windows中从命令行执行此操作的方法吗?我在Ruby和Python中已经看到了一些解决方案,但是如果可以管理的话,我希望有一个准系统的解决方案。
Mig82'1

1
@akhan添加一些内容对命令.gitignore-empty标志没有影响find。我的评论是关于删除.DS_Store目录树中的文件的,因此-empty可以应用该标志。
zerweck

67

安迪·莱斯特(Andy Lester)是对的,但是如果您的目录只需要为空,而不是目录,则可以.gitignore在其中放置一个空文件作为解决方法。

顺便说一句,这是一个实现问题,而不是基本的Git存储设计问题。正如在Git邮件列表中多次提到的那样,未实现此问题的原因是,没有人愿意为此提交补丁,而不是无法或不应该这样做。


4
我就是这么说的 我发布的FAQ片段中都提到了这两段。
安迪·莱斯特

1
我认为,旁听是令人讨厌且有用的-可以解决,只是在大多数情况下有如此简单的解决方法时不要期望很快。
wnoise

抱歉,我没有阅读最后一段,虽然我确实阅读了第一段,但是,我不确定为什么我会重复这些信息。
亚里斯多德·帕加尔兹

2
当然,这个额外的答案确实可以指出事实。
Michael Johnson

我在这里查看的情况是,如果该目录不存在并且默认情况下为空,则构建失败。但是它不必为空。创建一个.gitignore做正确的事情。
约书亚

33

Ruby on Rails的日志文件夹的创建方式:

mkdir log && touch log/.gitkeep && git add log/.gitkeep

现在,日志目录将包含在树中。部署时它非常有用,因此您无需编写例程即可创建日志目录。

可以通过发出以下命令来保留日志文件:

echo log/dev.log >> .gitignore

但您可能知道这一点。


23
这与Ruby on Rails有什么关系?
Quolonel问题


30

Git不会跟踪空目录。有关更多说明,请参见Git FAQ。建议的解决方法是将.gitignore文件放在空目录中。我不喜欢这种解决方案,因为.gitignore Unix约定“隐藏了”。也没有解释为什么目录为空。

我建议将README文件放在空目录中,解释为什么目录为空以及为什么需要在Git中对其进行跟踪。就README文件而言,就Git而言,该目录不再为空。

真正的问题是,为什么在git中需要空目录?通常,您具有某种构建脚本,可以在编译/运行之前创建空目录。如果没有,那就做一个。这比将空目录放入git更好。

因此,您有某些原因为什么需要在git中使用一个空目录。将该原因放在自述文件中。这样,其他开发人员(以及您将来的开发人员)就会知道为什么需要存在空目录。您还将知道,当解决了要求空目录的问题后,就可以删除空目录。


要列出每个空目录,请使用以下命令:

find -name .git -prune -o -type d -empty -print

要在每个空目录中创建占位符自述文件:

find -name .git -prune -o -type d -empty -exec sh -c \
  "echo this directory needs to be empty because reasons > {}/README.emptydir" \;

要忽略目录中除README文件以外的所有内容,请在您的计算机中放置以下几行.gitignore

path/to/emptydir/*
!path/to/emptydir/README.emptydir
path/to/otheremptydir/*
!path/to/otheremptydir/README.emptydir

另外,您可以排除每个自述文件而忽略它们:

path/to/emptydir/*
path/to/otheremptydir/*
!README.emptydir

在创建每个自述文件后列出它们:

find -name README.emptydir

28

警告:事实证明,这种调整并没有真正起作用。抱歉给你带来不便。

原始帖子如下:

我在玩Git内部构件时找到了解决方案!

  1. 假设您在存储库中。
  2. 创建您的空目录:

    $ mkdir path/to/empty-folder
    
  3. 使用管道命令和空树SHA-1将其添加到索引:

    $ git update-index --index-info
    040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904    path/to/empty-folder
    

    键入命令,然后输入第二行。按Enter,然后按Ctrl+ D终止输入。注意:格式为模式 [SPACE] 类型 [SPACE] SHA-1hash [TAB]路径(标签是很重要的,答案格式不保留它)。

  4. 而已!空文件夹在索引中。您要做的就是提交。

该解决方案很短,并且显然可以正常工作(请参见编辑!),但是它并不容易记住...

可以通过在其中创建一个新的空Git存储库cd并发出issue 来找到空树SHA-1 git write-tree,该存储库输出空树SHA-1。

编辑:

自找到以来,我一直在使用此解决方案。它看起来与创建子模块完全相同,但是在任何地方都没有定义模块。这会导致发行时出错git submodule init|update。问题是git update-index040000 tree零件重写为160000 commit

而且,放在该路径下的任何文件都不会被Git注意到,因为它认为它们属于其他存储库。这很讨厌,因为它很容易被忽略!

但是,如果您尚未(也不会)使用存储库中的任何Git子模块,并且“空”文件夹将保持为空,或者如果您希望Git知道其存在并忽略其内容,则可以使用这个调整。使用子模块的常规方法将花费更多的步骤进行此调整。


将空文件夹放入索引并提交后,是否有可能git svn dcommit获得所需的结果?
限量赎罪

2
这种调整不太可能与其他任何工具一起使用。像警告和编辑中所述,除非在非常有限的情况下,否则我不鼓励使用它。
ofavre 2014年

1
当然这就是为什么禁止使用git内部结构的原因。
Casey

@abhisekp怎么可能?
PyRulez'1

1
@PyRulez很好,在软件世界中,没有什么是不可能的。:D实际上,我遵循了答案。
abhisekp

21

假设您需要一个名为tmp的空目录:

$ mkdir tmp
$ touch tmp/.gitignore
$ git add tmp
$ echo '*' > tmp/.gitignore
$ git commit -m 'Empty directory' tmp

换句话说,您需要将.gitignore文件添加到索引中,然后才能告诉Git忽略它(以及空目录中的所有其他内容)。


11
两件事:您可以仅“ echo'*'> tmp / .gitignore”而不是触摸,并且在将文件添加到索引后,“ git commit -m”不会提交所做的更改。
ChristofferHammarström,2010年

6
如果只是这样做,echo bla > file您将不会得到,file: File exists因为>它将覆盖该文件(如果已存在)或创建一个新文件(如果不存在)。
psyrendust 2014年

3
/bin/sh文化假设!*如果“这里”是cshnoclobber设置了变量,则确实会得到file: File exists。如果有人说“我明白了”,请不要以为他们是白痴,然后回答“不,您不要”。* c2.com/cgi/wiki?AmericanCulturalAssumption
clacke

1
@clacke如果某人决定使用与其他人不同的外壳,则应明确指出是否遇到问题。与国籍不同,每个人都可以自由选择外壳。
SeldomNeedy

2
@SeldomNeedy也许他们正在寻求帮助,因为他们甚至不知道自己使用的外壳与其他人不同。
clacke '16

20

也许添加一个空目录似乎是阻力最小路径,因为您有希望该目录存在的脚本(也许因为它是生成的二进制文件的目标)。另一种方法是修改脚本以根据需要创建目录

mkdir --parents .generated/bin ## create a folder for storing generated binaries
mv myprogram1 myprogram2 .generated/bin ## populate the directory as needed

在此示例中,您可以签入到该目录的(断开)符号链接,以便您可以在没有“ .generation”前缀的情况下访问它(但这是可选的)。

ln -sf .generated/bin bin
git add bin

当您想要清理源代码树时,您可以:

rm -rf .generated ## this should be in a "clean" script or in a makefile

如果采用经常建议的方法来检查几乎为空的文件夹,则删除内容的复杂性较小,而无需同时删除“ .gitignore”文件。

您可以通过将以下内容添加到根.gitignore来忽略所有生成的文件:

.generated

1
注意:我建议的符号链接在干净的签出中“断开”,因为该.generated目录最初不存在。完成构建后,它将不再被破坏。
nobar 2012年

2
我同意,在某些情况下,这是一个很好的主意,但在其他情况下(例如,分发一个项目,在该项目中您拥有一个空的框架,其中包含诸如model /和views /的文件夹),您希望用户拥有这些目录,而不是无需手动阅读文档,而期望他们在克隆存储库后运行某种安装脚本可能会有点困难。我认为这个答案与@ john-mee的README答案相结合应该涵盖大多数(即使不是全部)情况。
moopet

14

我也一直面临着空目录的问题。使用占位符文件的问题是,如果不再需要它们,则需要创建它们并删除它们(因为稍后添加了子目录或文件。使用大的源代码树来管理这些占位符文件可能很麻烦且出错)易于。

这就是为什么我决定编写一个开源工具,该工具可以自动管理此类占位符文件的创建/删除。它是为.NET平台编写的,可在Mono(Linux的.NET)和Windows下运行。

看看:http : //code.google.com/p/markemptydirs


14

我喜欢@ Artur79和@mjs的答案,所以我一直将两者结合使用,并使其成为我们项目的标准。

find . -type d -empty -exec touch {}/.gitkeep \;

但是,只有少数开发人员可以在Mac或Linux上工作。在Windows上进行了大量工作,我找不到在其中完成相同功能的等效简单工具。有些人幸运地拥有了Cygwin因为其他原因安装了,但是仅仅为此开处方Cygwin似乎过头。

编辑以获得更好的解决方案

因此,由于大多数开发人员已经安装了Ant,因此我想到的第一件事就是将Ant构建文件放在一起以独立于平台来完成此工作。仍然可以在这里找到

但是,我后来认为最好将其变成一个小的实用程序命令,因此我使用Python重新创建了该命令并将其发布到此处的PyPI 。您可以通过简单地运行它来安装它:

pip3 install gitkeep2

它可以让您.gitkeep递归地创建和删除文件,还可以向它们的邻居添加消息,以了解为什么这些目录很重要。最后一点是奖金。我认为如果.gitkeep文件可以自我记录会很好。

$ gitkeep --help
Usage: gitkeep [OPTIONS] PATH

  Add a .gitkeep file to a directory in order to push them into a Git repo
  even if they're empty.

  Read more about why this is necessary at: https://git.wiki.kernel.org/inde
  x.php/Git_FAQ#Can_I_add_empty_directories.3F

Options:
  -r, --recursive     Add or remove the .gitkeep files recursively for all
                      sub-directories in the specified path.
  -l, --let-go        Remove the .gitkeep files from the specified path.
  -e, --empty         Create empty .gitkeep files. This will ignore any
                      message provided
  -m, --message TEXT  A message to be included in the .gitkeep file, ideally
                      used to explain why it's important to push the specified
                      directory to source control even if it's empty.
  -v, --verbose       Print out everything.
  --help              Show this message and exit.

希望对你有帮助。


13

您不能而且很遗憾将永远无法。这是Linus Torvald本人做出的决定。他知道什么对我们有好处。

我曾经读过的某处有一只咆哮。

我发现Re:空目录..,但也许还有另一个。

不幸的是,您必须忍受变通办法。


1
我知道您将其发布为一个错误参数的示例,但是我感谢该链接,因为它实际上是针对跟踪目录的合理参数。;-)
clacke

1
这个答案似乎不一致,因为Linus Torvald在下一篇关于所引用线程的文章中说,他希望他们需要添加目录跟踪:markmail.org/message/libip4vpvvxhyqbl。实际上,他说他“将欢迎[添加对跟踪空目录的支持]的补丁”
Patrick M

帕特里克(Patrick),他在那里也使用“白痴”一词。我怀疑他的措辞可以使这里的人们感到满意,因此我认为他不会自己对Git实施“愚蠢”的事情。
user2334883

10

添加.gitignore文件时,如果要在其中添加任何数量的内容(希望让Git忽略),则可能需要添加仅带有星号的一行,*以确保您不会意外添加被忽略的内容。


9

无法让Git跟踪目录,因此唯一的解决方案是在要跟踪Git的目录中添加一个占位符文件。

可以命名该文件并包含所需的任何内容,但是大多数人使用一个名为的空文件.gitkeep(尽管有些人更喜欢VCS无关的文件.keep)。

前缀 .标记为隐藏文件。

另一个想法是添加一个README文件,解释该目录的用途。


8

如前所述,不可能添加空目录,但这是一个将空.gitignore文件添加到所有目录的衬板。

ruby -e 'require "fileutils" ; Dir.glob(["target_directory","target_directory/**"]).each { |f| FileUtils.touch(File.join(f, ".gitignore")) if File.directory?(f) }'

我将其粘贴在Rakefile中以便于访问。


6
我宁愿使用find . -type d -empty -print0 | xargs --null bash -c 'for a; do { echo "*"; echo "!.gitignore"; } >>"$a/.gitignore"; done' --
Tino

8

Jamie Flournoy的解决方案效果很好。这是保留以下内容的增强版本.htaccess

# Ignore everything in this directory
*
# Except this file
!.gitignore
!.htaccess

有了这个解决方案,您可以提交一个空文件夹,例如/log/tmp或者/cache和文件夹将保持为空。


2
他想保留一个空目录而不是一个文件。
gvsrepins

2
我已经提到过,它将也保留.htaccess。例如:如果某个软件的日志文件目录(例如oxid eshop)不能通过Web访问,则该目录中将存在.htaccess。如果将上述.gitignore放在文件夹中,则不会提交.htaccess文件,并且可以通过Web访问该文件夹。
罗马

如果您有一个受版本控制的.htaccess文件,那么您已经具有包含该文件的目录在版本控制下。因此,问题已经解决-.gitignore文件变得无关紧要。
Ponkadoodle

1
@Wallacoloo与您正确的问题相关,不过该文件很有用,我将其用于上载目录,例如文件应受.htaccess保护的目录。与罗马人的解释相反,.htaccess文件将被提交,因为它被忽略规则排除。[我知道是旧线程]
David

7

我总是构建一个函数来检查所需的文件夹结构,并在项目中为我构建它。由于空文件夹由代理保存在Git中,因此可以解决此问题。

function check_page_custom_folder_structure () {
    if (!is_dir(TEMPLATEPATH."/page-customs"))
        mkdir(TEMPLATEPATH."/page-customs");    
    if (!is_dir(TEMPLATEPATH."/page-customs/css"))
        mkdir(TEMPLATEPATH."/page-customs/css");
    if (!is_dir(TEMPLATEPATH."/page-customs/js"))
        mkdir(TEMPLATEPATH."/page-customs/js");
}

这是用PHP编写的,但是我确定大多数语言都支持相同的功能,并且由于文件夹的创建是由应用程序负责的,因此文件夹将始终存在。


2
只是为了让我们都在同一页面上,所以我不再这样做了。浪费时间。该.gitkeep公约是一个更好的做法。
轻微的绒毛2014年

我看不到这怎么浪费时间。当您的TEMPLATEPATH很明显是动态的时,您不能使用.gitkeep解决方案。即使使用非动态文件夹结构,您也应该添加一些其他内容,而不是删除检查目录的良好解决方案,例如检查权限和chmod文件。添加一种在全局.gitignore内标记目录的方法对我来说是完美的。像#keep / path / to / dir
Jochen Schultz

7

这是一个hack,但是很有趣,它可以工作(Git 2.2.1)。与@Teka建议类似,但更容易记住:

  • 将子模块添加到任何存储库(git submodule add path_to_repo
  • 这将添加一个文件夹和一个文件 .submodules。提交更改。
  • 删除.submodules文件并提交更改。

现在,您有一个在检出提交时创建的目录。但是,有趣的是,如果查看此文件的树对象的内容,则会得到:

致命的:无效的对象名称b64338b90b4209263b50244d18278c0999867193

我不鼓励使用它,因为它可能会在以后的Git版本中停止工作。这可能会使您的存储库损坏。


这实际上有效,但是我认为混淆了IntelliJ ...:|
rogerdpack

我基于此创建了一个没有这些缺点的更好的解决方案:stackoverflow.com/a/58543445/277882
ntninja

7

许多人已经回答了这个问题。只需在此处添加PowerShell版本。

在目录中找到所有空文件夹

在其中添加一个空的.gitkeep文件

Get-ChildItem 'Path to your Folder' -Recurse -Directory | Where-Object {[System.IO.Directory]::GetFileSystemEntries($_.FullName).Count -eq 0} | ForEach-Object { New-Item ($_.FullName + "\.gitkeep") -ItemType file}


6

如果要添加一个在多个语义目录中包含大量瞬态数据的文件夹,则一种方法是在根.gitignore中添加类似的内容。

/app/data/**/*.* !/app/data/**/*.md

然后,您可以*.md在每个目录中提交描述性的README.md文件(或空白文件,没关系,只要您可以像在这种情况下一样以它们为唯一目标)就可以确保目录都保留在存储库中,但是文件(带有扩展名)将被忽略。局限性:.目录名称中不允许使用!

您可以使用xml / images文件或其他文件填充所有这些目录,并在以下目录中添加更多目录 /app/data/随着应用程序存储需求的发展在一段时间内(README.md文件用于烧录每个存储目录的描述)究竟)。

无需.gitignore通过.gitignore为每个新目录创建新目录来进一步更改目录或分散目录。可能不是最聪明的解决方案,但简洁明了,并且始终对我有用。漂亮又简单!;)

在此处输入图片说明


6

一种简单的方法是将.gitkeep文件添加到您希望(当前)保持空白的目录中。

请参阅此SOF答案以获取更多信息-这也解释了为什么有些人觉得添加.gitignore文件的竞争惯例(如此处许多答案所述)令人困惑。


4

在竞争中增加了一个选项。

假设您要在其中添加目录git,出于与,的所有相关目的git,应保留为空,并且永远不要跟踪其内容,.gitignore如这里多次建议的那样,就可以解决问题。

如前所述,格式为:

*
!.gitignore

现在,如果你想有一个办法做到这一点在命令行中,一举,而里面的目录要添加,你可以执行:

$ echo "*" > .gitignore && echo '!.gitignore' >> .gitignore && git add .gitignore

我自己有一个用于执行此操作的shell脚本。随意命名脚本,然后将其添加到包含路径中的某个位置,或直接引用它:

#!/bin/bash

dir=''

if [ "$1" != "" ]; then
    dir="$1/"
fi

echo "*" > $dir.gitignore && \
echo '!.gitignore' >> $dir.gitignore && \
git add $dir.gitignore

这样,您可以在要添加的目录中执行它,也可以引用该目录作为它的第一个也是唯一的参数:

$ ignore_dir ./some/directory

另一种选择(响应由@GreenAsJade评论),如果你想跟踪一个空文件夹是MAY包含跟踪文件在未来,但将是空的,现在,你可以ommit的*.gitignore文件,并检查英寸基本上,所有文件说的是“不要忽略 ”,否则,该目录为空并被跟踪。

您的.gitignore文件如下所示:

!.gitignore

就这样,签入,您将拥有一个空的但尚未跟踪的目录,以后可以在其中跟踪文件。

我建议在文件中保留一行的.gitignore目的是为了达到目的。否则,某些人可能会考虑将其删除。如果您将注释放在行上方,则可能会有所帮助。


4

有时,您必须处理不良的书面库或软件,这些库或软件需要“真实”的空目录和现有目录。放在一个简单的.gitignore.keep可能会破坏它们并导致错误。在这些情况下,以下内容可能会有所帮助,但不能保证...

首先创建所需的目录:

mkdir empty

然后,您将一个损坏的符号链接添加到该目录(但在上述使用案例之外的任何其他情况下,请使用README带说明的符号):

ln -s .this.directory empty/.keep

要忽略此目录中的文件,可以将其添加到根目录中.gitignore

echo "/empty" >> .gitignore

要添加被忽略的文件,请使用参数来强制它:

git add -f empty/.keep

提交后,您的索引中的符号链接断开,并且git创建目录。断开的链接具有一些优点,因为它不是常规文件,也不指向常规文件。因此,它甚至适合问题“(不包含任何文件)”部分,而不是意图,而是含义:

find empty -type f

此命令显示为空结果,因为此目录中没有文件。因此,大多数将所有文件都放在目录中的应用程序通常看不到此链接,至少在它们确实存在“文件存在”或“可读”的情况下。即使是某些脚本,也无法在其中找到任何文件:

$ php -r "var_export(glob('empty/.*'));"
array (
  0 => 'empty/.',
  1 => 'empty/..',
)

但是我强烈建议仅在特殊情况下使用此解决方案,README在空目录中编写好的文件通常是更好的解决方案。(而且我不知道这是否适用于Windows文件系统...)


4

使用残破的GIT子模块引用阅读@ofavre@ stanislav-bashkyrtsev的答案来创建GIT目录,令我感到惊讶的是,没有人提出这个想法的简单修改,以使整个过程理智而安全:

与其添加一个假的子模块到GIT中,不如添加一个真正的空子模块

输入:https : //gitlab.com/empty-repo/empty.git

一个GIT存储库,其中只有一个提交:

commit e84d7b81f0033399e325b8037ed2b801a5c994e0
Author: Nobody <none>
Date: Thu Jan 1 00:00:00 1970 +0000

没有消息,没有提交的文件。

用法

要将空目录添加到您的GIT存储库中:

git submodule add https://gitlab.com/empty-repo/empty.git path/to/dir

要将所有现有的空目录转换为子模块:

find . -type d -empty -delete -exec git submodule add -f https://gitlab.com/empty-repo/empty.git \{\} \;

Git在创建子模块引用时将存储最新的提交哈希,因此您不必担心我(或GitLab)使用它来注入恶意文件。不幸的是,我没有找到任何方法来强制在结帐期间使用哪个提交ID,因此您必须手动检查参考提交ID是否正在e84d7b81f0033399e325b8037ed2b801a5c994e0使用git submodule status在添加回购后。

还没本地的解决方案,但没有人我们大概可以有最好的得到他们的手真的真的在GIT代码库脏。

附录:重新创建此提交

您应该能够使用(在一个空目录中)重新创建此确切的提交:

# Initialize new GIT repository
git init

# Set author data (don't set it as part of the `git commit` command or your default data will be stored as “commit author”)
git config --local user.name "Nobody"
git config --local user.email "none"

# Set both the commit and the author date to the start of the Unix epoch (this cannot be done using `git commit` directly)
export GIT_AUTHOR_DATE="Thu Jan 1 00:00:00 1970 +0000"
export GIT_COMMITTER_DATE="Thu Jan 1 00:00:00 1970 +0000"

# Add root commit
git commit --allow-empty --allow-empty-message --no-edit

创建可重现的GIT提交非常困难……


3

你不能 这是Git维护者的有意设计决定。基本上,像Git这样的源代码管理系统的目的是管理源代码,而空目录不是源代码。Git通常也被描述为内容跟踪器,同样,空目录也不是内容(实际上恰恰相反),因此它们不会被跟踪。


60
我反对这种观点。结构就是内容,您命名的所有内容都对内容有所贡献。
ThomasH 2011年

20
空文件也不是源代码或内容。这只是一个名字。但是,Git会愉快地跟踪空文件。我认为让Git拒绝跟踪空目录不是故意的设计决定。我认为跟踪空目录是一项功能,在99%的时间中根本不需要,因此,他们不必费心去做使其正常工作所需的额外工作。如果有人非常想实现该功能,Git可以做到。我怀疑如果正确完成Git维护者会反对这样的补丁。
Dan Moulding

1
@TobyAllen是更新的FAQ链接。最佳答案也是FAQ建议的更精确的说明。
Daniel Da Cunha

3
这是一项缺少的功能(优先级较低),不是故意的限制。来自Git常见问题解答:当前,Git索引(临时区域)的设计仅允许列出文件,并且没有足够胜任能力进行更改以允许空目录的人对此情况已采取足够的补救措施。
jbo5112 2013年

真的不同意。我可以找到各种原因来跟踪空文件夹。例如,我正在为我的项目开发一个非常轻量级的PHP MVC框架。我有用于放置模型,视图等的特定文件夹。当基于我的框架创建新站点时,这些文件夹为空,因为默认情况下没有模型或视图,但是我确实需要该文件夹存在,否则我的框架就赢了不行!
Gladen 2013年

2

您可以将此代码另存为create_readme.php并从Git项目的根目录运行PHP代码。

> php create_readme.php

它将自述文件添加到所有空目录中,以便将这些目录添加到索引中。

<?php
    $path = realpath('.');
    $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path),       RecursiveIteratorIterator::SELF_FIRST);
    foreach($objects as $name => $object){
        if ( is_dir($name) && ! is_empty_folder($name) ){
            echo "$name\n" ;
            exec("touch ".$name."/"."README");
        }
    }

    function is_empty_folder($folder) {
        $files = opendir($folder);
        while ($file = readdir($files)) {
            if ($file != '.' && $file != '..')
                return true; // Not empty
            }
        }
?>

然后做

git commit -m "message"
git push
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.