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

5302

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


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

11

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

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

前缀的.标记它为隐藏文件。

另一个想法是添加一个README文件,解释该目录将用于什么。


10

一份 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}

另外,ni -p $_.FullName -n .gitignore -v "*`r`n!.gitignore" - Gregor y

9

如前所述,无法添加空目录,但是以下是一个一行代码的方式,可以向所有目录添加空的.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

9

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 访问。 - Roman
如果您有一个在版本控制下的 .htaccess 文件,那么包含它的目录已经在版本控制下了。因此,问题已经解决 - .gitignore 文件变得无关紧要。 - Ponkadoodle
1
@Wallacoloo 关于你的问题,你是对的,但是这个文件很有用,我会将其用于上传目录,以便文件受到.htaccess的保护。与Roman的解释相反,.htaccess文件将被提交,因为它被忽略规则所排除。【旧帖子,我知道】 - David

8
我总是编写一个函数来检查我所需的文件夹结构,并在项目中为我构建它。这样可以解决这个问题,因为空文件夹通过代理在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中,但我相信大多数语言都支持相同的功能,并且由应用程序负责创建文件夹,因此文件夹始终存在。


3
只是为了让我们都明白,我不再这样做了。这是浪费时间。.gitkeep约定是更好的实践。 - Mild Fuzz
我看不出这怎么会是浪费时间。当您的TEMPLATEPATH显然是动态的时,您不能使用.gitkeep解决方案。即使是非动态文件夹结构,您也应该添加一些其他内容,而不是删除检查目录的非常好的解决方案,例如检查权限并chmod文件。在全局.gitignore中标记目录的方法对我来说将是完美的。类似于#keep /path/to/dir - Jochen Schultz

8

以下是一种 hack 方法,但很有趣的是它能够使用(Git 2.2.1)。与 @Teka 建议的方法类似,但更易于记忆:

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

现在,在检出时会创建一个目录。有趣的是,如果查看该文件树对象内容,则会返回:

fatal: Not a valid object name b64338b90b4209263b50244d18278c0999867193

不过我不鼓励使用此方法,因为它可能无法在 Git 的未来版本中运行,并可能导致存储库损坏。


这实际上是有效的,但我认为它让 IntelliJ 非常困惑... :| - rogerdpack
我基于这个创建了一个更好的解决方案,它没有这些缺点:https://dev59.com/QnVD5IYBdhLWcg3wBWzd#58543445 - ntninja

8
如果您想添加一个包含大量短暂数据的文件夹,并且这些数据分布在多个语义目录中,那么一种方法是将以下内容添加到您的根目录 .gitignore 文件中...

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

然后,您可以在每个目录中提交描述性README.md文件(或空文件,不要紧,只要您可以像在这种情况下使用*.md一样唯一地定位它们),以确保目录仍然是存储库的一部分,但文件(带扩展名)将被忽略。限制:目录名称中不允许使用“.”!
您可以使用xml / images文件或其他文件填充所有这些目录,并随着应用程序存储需求的发展,在/ app / data / 下添加更多目录(README.md文件用于烧录每个存储目录的描述)。
没有必要进一步修改您的.gitignore或通过为每个新目录创建新的.gitignore来进行去中心化。可能不是最聪明的解决方案,但从gitignore角度来看很简洁,对我来说总是有效的。漂亮而简单!;)

enter image description here


7
有时候你需要处理一些糟糕的编写的库或软件,它们需要一个“真正”的空目录。放置一个简单的.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文件系统...)


7

一种简单的方法是在要(目前)保持为空的目录中添加一个.gitkeep文件。

请参阅此SOF答案以获取更多信息-该答案还解释了为什么一些人发现添加.gitignore文件(如许多答案中所述)具有竞争性和混淆性。


5

为混乱的选项添加一个更多的选项。

假设您想要将一个目录添加到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的评论),即在.gitignore文件中省略*,并将其检入。基本上,所有文件都在说“不要忽略我”,但除此之外,该目录为空且已被跟踪。

您的.gitignore文件应如下所示:

!.gitignore

就这样,检查一下,你就有了一个空的、但被跟踪的目录,以后可以在其中跟踪文件。

我建议保留这一行代码是因为它给.gitignore文件赋予了目的。否则,后来的某个人可能会想要删除它。如果在这行代码上方加上注释,可能会有所帮助。


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