如何向Git仓库添加一个空目录?

5302

我该如何将空目录(不包含任何文件)添加到Git仓库中?


23
虽然它没有什么用处,但是有一种方法可以将一个空(真正的空)目录添加到你的版本库中。但是,使用当前版本的Git无法进行检出。 - tiwo
37个回答

5062

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

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

那么你不必像m104的解决方案中所必须的那样正确排序。

这也有一个好处,当您执行git status时,该目录中的文件不会显示为“未跟踪”。

保留@GreenAsJade的评论:

我认为值得注意的是,这个解决方案正是问题所要求的,但可能不是很多人寻找的。此解决方案保证目录保持为空。它说:“我绝对不想在这里检查文件。”而不是“我没有任何文件要在这里检查,但我需要这个目录,在后面可能会有文件。”


46
我认为应该将@JohnMee提出的README解决方案与这个方案一起使用; .gitignore文件提供了我们想要排除在版本控制之外的内容的说明,而README文件则解释了目录的目的,这两者都是非常重要的信息。 - pedromanoel
26
我会把README文件的内容作为注释写进.gitignore文件中。 - Carlos Campderrós
99
发现一个不同之处:1)一个空文件夹,2)一个包含.gitignore文件的文件夹。;-) - Peter Perháč
11
这很适合用作“缓存”文件夹。 - redolent
20
不幸的是,这导致了一个非空目录,其中包含一个隐藏文件。 - pedorro
2
在某些情况下,@pedorro 正是你想要的。 - Peter Kionga-Kamau

1211
你做不到。请参考Git FAQ
目前,git索引(暂存区)的设计仅允许列出文件,并且没有能够使空目录成为可能的能力强大的人关注这个情况以解决它。
当向其中添加文件时,目录会自动添加。也就是说,不必将目录添加到存储库中,并且不会单独跟踪目录。
你可以使用"git add <dir>"命令来添加其中的文件。
如果你真的需要一个目录在检出中存在,你应该在其中创建一个文件。.gitignore很适合这个目的;你可以让它保持为空,或填写你希望显示在目录中的文件名。

如果你考虑到一个.gitignore文件不为空的情况,应该明确指出这是不可能的。此外,如果从远程删除了一个目录,在拉取操作中会删除文件,但本地的空目录不会被删除。 - MayTheSForceBeWithYou

1096

在目录中创建一个名为.gitkeep的空文件,并使用git add命令添加它。

在类Unix系统上,这将默认为一个隐藏文件,但它会强制Git确认该目录存在,因为它现在有了内容。

另外请注意,此文件名称并没有特别之处。您可以随意命名。对于Git来说,重要的是文件夹内含有某些内容。


300
.gitkeep 并非 Git 所规定,容易让人对其含义产生疑问,导致他们去搜索,最终到达此处。.git 前缀惯例应保留给 Git 本身使用的文件和目录。 - t-mart
21
.git前缀约定应该保留……”为什么?Git是否要求进行此类保留? - lmat - Reinstate Monica
29
在这种情况下,一个 READMEABOUT 文件会同样好甚至更好。留下一条便条给下一个人,就像在没有 URL 的时候我们都曾做过的那样。 - Dave
12
如果您正在编写一个应该测试空目录上的代码的单元测试,那么这个方法是不起作用的。 - thebjorn
21
我认为这一点并不令人困惑。事实上,我认为将其称为".gitkeep"非常直观。对我来说,称之为".gitignore"听起来反而有些矛盾。因此,这只是个人口味的问题。 - Mig82
显示剩余6条评论

555

您可以在目录中放置一个README文件,解释为什么您想要将这个空的目录放入代码库中。


478
touch .placeholder
在Linux上,这将创建一个名为.placeholder的空文件。值得一提的是,此名称与git无关,并且该方法在系统中的其他位置(例如/etc/cron.d/.placeholder)中也被使用。其次,正如另一位用户指出的那样,.git前缀约定可以保留供Git本身用于配置目的的文件和目录。
或者,如另一个答案中所述,该目录可以包含一个描述性的README.md文件
无论哪种方式,都要求该文件的存在不会导致应用程序崩溃。

1
使用.keep而不是.gitkeep的原因非常好。在简单和不易混淆之间取得了很好的平衡。命名空间似乎很重要,不应该打破.git...看起来像git自己的文件命名空间。附加文档可以放在项目的全局readme或编码风格指南或本地readme中。如果您已经采用了.gitkeep的习惯,请找到这些文件并将它们重命名为:git mv .gitkeep .keep。拥抱变化!Git文档推荐的.gitignore解决方案似乎是一个hacky的解决方法,过于复杂。 - mit
在Windows上,touch命令是Git Bash(资源管理器插件)的一部分;另一个选项是使用WSL - Wolf

373

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

首先说明:

在Git版本控制系统下,空目录不能作为树的一部分被跟踪。

它只是不会被追踪。但是,在某些情况下,“版本控制”空目录可能具有意义,例如:

  • 搭建一个 预定义的文件夹结构,使其对存储库的每个用户/贡献者都可以使用;或者,作为上述情况的特殊情况,创建一个用于 临时文件 的文件夹,如cache/logs/ 目录,在这里我们想提供文件夹但是要.gitignore其内容。
  • 与上面有关,有些项目没有一些文件夹无法正常工作(这通常是一个糟糕设计项目的提示,但它是现实世界中频繁出现的场景,也许有权限问题需要解决)。

一些建议的解决方法

许多用户建议:

  1. 放置一个README文件或另一个带有一些内容的文件,以使目录非空,或者
  2. 创建一个.gitignore文件,其中包含一种“反向逻辑”(即包括所有文件),这最终实现了第1种方法的相同目的。

虽然这两个解决方案肯定有效,但我认为它们与Git版本控制的有意义的方法不一致。

  • 为什么你必须放置虚假文件或可能并不真正需要的README文件到你的项目中?
  • 为什么要使用.gitignore来执行相反于其用途(保留文件)的操作,尽管这是可能的?

.gitkeep方法

使用一个名为.gitkeep的空文件来强制将文件夹存在于版本控制系统中。

虽然看起来并没有什么大的区别:

  • 您可以使用一个专门用于保存文件夹的文件,而不会在其中放置任何您不想放置的信息。

    例如,您应该将README作为有用信息的README,而不是为了保留文件夹而借口。

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

  • 将其命名为.gitkeep,从文件名本身就非常明确和简单(对于其他开发人员也是如此,这对于共享项目和Git存储库的核心目的之一很有好处),表明此文件是

    • 与代码无关的文件(因为有前导点和名称)
    • 明显与Git有关
    • 其目的(keep)清晰地说明并且语义上与ignore相反

采用

我看到像LaravelAngular-CLI这样的重要框架采用了.gitkeep方法。


141

如其他答案所述,Git无法在其暂存区中表示空目录。(请参见Git FAQ。)但是,如果对于你的目的来说,一个目录只要包含一个.gitignore文件就足够为空,那么你可以通过以下方式仅在空目录中创建.gitignore文件:

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

23
您可以忽略.git目录:find . -name .git -prune -o -type d -empty -exec touch {}/.gitignore \; - steffen
4
大多数情况下更简单的变体是 find * -type d -empty -exec touch {}/.gitignore \;。(注:该命令会在查找到的所有空文件夹中创建名为 ".gitignore" 的文件。) - akhan
3
由于OS X在几乎每个目录下都会创建一个.DS_Store文件,因此此方法在该系统上不起作用。我找到的唯一(危险的!)解决方法是首先通过find . -name .DS_Store -exec rm {} \;命令删除所有.DS_Store文件,然后再使用此答案中提供的首选变体。 请确保只在正确的文件夹中执行此操作! - zerweck
2
有人知道如何在Windows命令行中完成这个任务吗?我看到了一些Ruby和Python的解决方案,但如果可能的话,我想要一个最简单的解决方案。 - Mig82
2
@akhan 将某些内容添加到 .gitignore 中对 find 命令的 -empty 标志没有影响。我的评论是关于删除目录树中的 .DS_Store 文件,以便可以应用 -empty 标志。 - zerweck
显示剩余2条评论

80

安迪·莱斯特(Andy Lester)说得对,但如果您的目录只需要是空的,而不是真正意义上的“空”,那么您可以将一个空的.gitignore文件作为解决方法放在里面。

另外,这是一个实现问题,而不是一个基本的Git存储设计问题。正如在Git邮件列表中多次提到的那样,之所以还没有实现这个功能是因为没有人关注到提交一个补丁,而不是不能或不应该做。


41
在空目录中添加一个名为.gitkeep的文件,并提交。
touch .gitkeep

.gitkeep是一个隐藏文件,在Linux中列出它需要运行命令。
ll -a

这是Git遵循的标准。

1
你有关于“这是Git遵循的标准”的参考资料吗?我不认为是这样的。我认为Git不在乎文件的命名方式。 - mkrieger1

40
TL;DR:将文件放入目录中,git 将跟踪该文件。(说真的,这是官方的解决方法)
但我建议:让构建脚本或部署脚本在站点上创建目录。
官方方式:
Git不会跟踪空目录。详细信息请参阅官方Git FAQ。建议的解决方法是在空目录中放置一个.gitignore文件。有了这个文件,目录就不再为空,Git会跟踪它。
我不喜欢这个解决方法。.gitignore文件的作用是忽略东西,但在这里却用来保留某些东西。
一个常见的解决方法(对这个解决方法的解决方法)是将文件命名为.gitkeep。这至少在文件名中表达了意图。此外,这似乎在一些项目中达成了共识。Git本身并不关心文件的命名,它只关心目录是否为空。

有一个问题是.gitkeep.gitignore共同面临的:根据Unix约定,这些文件是隐藏的。一些工具,比如lscp dir/*,会假装这些文件不存在,表现得好像目录是空的。而其他工具,比如find -empty,则不会如此。新手Unix用户可能会被这个问题困扰。有经验的Unix用户会推断出存在隐藏文件并进行检查。无论如何,这是一个可以避免的烦恼。

顺便说一下:解决"隐藏文件问题"的一个简单方法是将文件命名为gitkeep(不带前导点)。我们还可以更进一步,将文件命名为README。然后,在文件中解释为什么需要将目录保持空白并在git中进行跟踪。这样其他开发人员(包括未来的你)就可以了解为什么事情是这样的。

总结:在目录中放置一个文件,现在(原本为空的)目录就被git跟踪了。

潜在问题:目录不再为空。

假设你需要空目录是因为你要在其中收集文件以供以后处理。但现在你不仅有了你想要的文件,还有一个叫做.gitignore或gitkeep的流氓文件,或者其他类似的文件。这可能会使简单的bash构造(如for file in dirname/*)变得复杂,因为你需要排除或特殊处理这个额外的文件。
Git不想跟踪空目录。试图让git跟踪空目录会牺牲你想要保留的东西:空目录本身。
此外:项目目录中的虚假“空”目录是潜在问题。一个新的开发者,或者未来的你,会碰到这个空目录,并想知道为什么它需要存在。你可能会删除这个目录。你可能会在其中放入其他文件。你甚至可能创建一个第二个工作流程,也使用这个空目录。然后在未来的某个时候,两个使用空目录的工作流程同时运行,所有脚本都失败了,因为这些文件毫无意义,两个团队都在想其他文件是从哪里来的。
我的建议是:让一个构建脚本或部署脚本在站点上创建目录。
让我们退后几步。在你问如何使git跟踪空目录之前。
那时你可能遇到的情况是:你有一个需要空目录才能工作的工具。你想要部署/分发这个工具,并且希望空目录也被部署。问题是:git不跟踪空目录。
现在,不要试图让git跟踪空目录,让我们探索其他选项。也许(希望如此)你有一个部署脚本。让部署脚本在git克隆后创建目录。或者你有一个构建脚本。让构建脚本在编译后创建目录。甚至可以修改工具本身,在使用之前检查并创建目录。
如果该工具旨在在不同环境中由人类使用,那么我会让工具本身检查并创建目录。如果你无法修改工具,或者工具以高度自动化的方式使用(docker容器部署、工作、销毁),那么部署脚本将是创建目录的好地方。
我认为这是解决问题的更明智的方法。构建脚本和部署脚本旨在准备运行程序所需的内容。你的工具需要一个空目录。所以使用这些脚本来创建空目录。
奖励:当要使用时,保证目录是真正空的。其他开发人员(包括未来的你)也不会在代码库中遇到一个“空”目录并想知道为什么需要它。
简而言之:让构建脚本或部署脚本在站点上创建空目录,或者让工具在使用之前检查并创建目录。
以下命令可能会对您继承的项目中包含空目录或“空”目录有所帮助。
要列出所有空目录:
find -type d -empty

同样的,但避免查看.git目录:
find -name .git -prune -o -type d -empty -print

列出包含名为.gitkeep的文件的每个目录:
find -type f -name .gitkeep

列出每个目录及其包含的文件数量:
find -type f -printf "%h\n" | sort | uniq -c | sort -n

现在您可以检查所有只包含一个文件的目录,并检查它是否是一个“git keep”文件。请注意,此命令不会列出真正为空的目录。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接