题
我怎么可以添加一个空的目录(不包含任何文件)以个混库?
解决方案
使目录保持(几乎)为空(在存储库中)的另一种方法是在该目录中创建一个包含以下四行的.gitignore
文件:
# Ignore everything in this directory
*
# Except this file
!.gitignore
然后,您无需按照m104的解决方案中的方式完成订单。
这也带来了以下好处:该目录中的文件不会显示为<!> quot; untracked <!> quot;当你做一个git状态时。
使 @GreenAsJade 的评论持久:
我认为值得注意的是,这个解决方案确切地解决了问题所要求的问题,但也许并不是许多人在寻找这个问题。此解决方案可确保目录保持为空。它说<!>“我真的不想在这里检查文件<!>”;与<!>相反,我没有任何文件要在这里检查,但是,我需要这里的目录,文件可能会在稍后出现<!>“。
其他提示
你做不到。请参阅 Git常见问题解答。
目前设计的git索引 (暂存区)只允许文件到 被列出,并没有人足够胜任 使更改允许为空 目录已经足够关心了 这种情况可以解决它。
自动添加目录 在其中添加文件时。那 是的,目录永远不必添加 到存储库,并没有被跟踪 他们自己。
你可以说<!>“;
git add <dir>
<!>”;而且它 将在那里添加文件。如果你真的需要一个目录 在结帐时你应该创建一个 文件在里面。 .gitignore效果很好 这个目的;你可以把它留空 或填写您的文件名称 期望出现在目录中。
在目录中创建一个名为.gitkeep
的空文件,并添加该文件。
您始终可以在目录中放置一个README文件,并说明您为什么要在存储库中使用此目录(否则为空)。
touch .keep
在Linux上,这会创建一个名为.keep
的空文件。此名称优先于.gitkeep
,因为前者与Git无关,而后者则特定于Git。其次,正如另一位用户所说,.git
前缀约定应保留给Git本身使用的文件和目录。
或者,如另一个答案中所述,该目录可以包含描述性 README
或README.md
文件。
当然,这要求文件的存在不会导致应用程序中断。
为什么我们需要空版本的文件夹
首先第一件事情:
一个空的目录 不可能是部分的一棵树下从初版本控制系统.
它根本不会被跟踪。但在有些情况下在其"版本控制的"空目录可以有意义的,例如:
- 一个脚手架 预先定义的文件夹结构, ,使它可为每一个用户/遣国的存储库;或者,作为一个专门的情况下以上时,创建一个文件夹 临时文件, 如一
cache/
或logs/
目录,其中我们想要提供的文件夹,但.gitignore
它的内容 - 有关上述,一些项目 不会工作如果没有一些文件夹 (这往往是一个暗示的设计不当的项目,但它是一个经常现实世界的情景,也许有可能是,比如说,权限的问题加以解决).
一些建议的解决方法
许多用户的建议:
- 把一个
README
文件或其他文件的一些内容,以便使目录非空,或 - 创建一个
.gitignore
文件有一种"反向逻辑"(即包括所有的文件),结束时,服务于同一目的的方法#1.
同时 这两个解决方案当然的工作 我发现它们不符合一个有意义的方式件版本控制。
- 为什么你应该把伪造文件或者自述,也许你不是真想在你的的项目呢?
- 为什么使用
.gitignore
要做的事情(保持 文件),是非常相反的是什么意思(不包括 文件),虽然它是可能的吗?
.gitkeep的方法
使用 空 文件称为 .gitkeep
为了力的存在文件夹中的版本控制系统。
虽然它可能似乎没有这么大的差别:
你使用一个文件 单 目的保持的文件夹。你不要放在那里的任何信息,你不想放。
例如,应使用自述文件作为,那么,自述的有用信息,而不是作为一个借口,以保留该文件夹。
分离的关切总是一件好事,你仍然可以添加一个
.gitignore
忽略不需要的文件。它命名
.gitkeep
使得它非常明确和直接从该文件本身(而且也 其他开发商, ,这是很好的一个共同项目和的一个核心目的的个混库),该文件- 一个文件无关的代码(因为领先点和名称)
- 文件明确相关件
- 其目(保持)是清楚的说明和一致和在语义上相对于其含义 忽略
通过
如其他答案中所述,Git无法在其暂存区域中表示空目录。 (请参阅 Git常见问题解答。)但是,如果,对于您而言目的,如果目录只包含.gitignore
文件,则该目录足够空,那么您只能通过以下方式在空目录中创建<=>文件:
find . -type d -empty -exec touch {}/.gitignore \;
Andy Lester是对的,但如果您的目录只需要为空,而不是为空为空,则可以在其中放置一个空的.gitignore
文件作为解决方法。
顺便说一下,这是一个实现问题,而不是基本的Git存储设计问题。正如在Git邮件列表中多次提到的那样,没有实现这一点的原因是没有人关心为它提交补丁,而不是它不能<!>#8217; t或者不应该<!> #8217;完成。
Ruby on Rails 日志文件夹创建方式:
mkdir log && touch log/.gitkeep && git add log/.gitkeep
现在日志目录将包含在树中。它在部署时非常有用,因此您不必编写例程来创建日志目录。
可以通过发出
来阻止日志文件echo log/dev.log >> .gitignore
但你可能知道。
Git不会跟踪空目录。有关更多说明,请参阅 Git常见问题解答。建议的解决方法是将.gitignore
文件放在空目录中。我不喜欢这个解决方案,因为<=>是<!>“隐藏<!>”;通过Unix惯例。也没有解释为什么目录是空的。
我建议将一个README文件放在空目录中,解释为什么目录为空以及为什么需要在Git中跟踪它。有了README文件,就Git而言,目录不再是空的。
真正的问题是为什么你需要git中的空目录?通常你有一些构建脚本可以在编译/运行之前创建空目录。如果没有,那就做一个。这是一个比将空目录放在git中更好的解决方案。
所以你有理由在git中需要一个空目录。把这个原因放在README文件中。这样,其他开发人员(以及未来的你)知道为什么空目录需要在那里。您还将知道,当解决了需要空目录的问题时,您可以删除空目录。
要列出每个空目录,请使用以下命令:
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文件之外的目录中的所有内容,请在<=>:
中添加以下行path/to/emptydir/*
!path/to/emptydir/README.emptydir
path/to/otheremptydir/*
!path/to/otheremptydir/README.emptydir
或者,您可以排除每个 README文件被忽略:
path/to/emptydir/*
path/to/otheremptydir/*
!README.emptydir
列出每个自述文件后的每个自述文件:
find -name README.emptydir
警告:此调整并非真正有效。很抱歉给您带来不便。
以下原帖:
我在玩Git内部时找到了解决方案!
- 假设您在存储库中。
-
创建空目录:
$ mkdir path/to/empty-folder
-
使用管道命令和空树 SHA-1 <将其添加到索引中/一个>:
$ git update-index --index-info 040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 path/to/empty-folder
键入命令,然后输入第二行。按 Enter 然后按 Ctrl + D 以终止输入。 注意:格式为模式 [SPACE] 类型 [SPACE] SHA-1hash [TAB] 路径(选项卡很重要,答案格式不保留它。)
-
就是这样!您的空文件夹位于索引中。你所要做的就是提交。
醇>
此解决方案很短,显然效果很好(参见编辑!),但这并不容易记住......
可以通过创建一个新的空Git存储库来找到空树SHA-1,cd
到它并发出git write-tree
,它输出空树SHA-1。
修改强>
我发现它以来一直在使用这个解决方案。它似乎与创建子模块的工作方式完全相同,只是在任何地方都没有定义模块。
这会在发出git submodule init|update
时导致错误。
问题是git update-index
将040000 tree
部分重写为160000 commit
。
此外,放在该路径下的任何文件都不会被Git注意到,因为它认为它们属于某个其他存储库。这很讨厌,因为它很容易被忽视!
但是,如果您还没有(并且不会)在您的存储库中使用任何Git子模块,并且<!> quot; empty <!>;文件夹将保持为空或如果您希望Git知道它的存在并忽略其内容,您可以使用此调整。按照惯常的方式使用子模块需要采取更多步骤进行调整。
也许添加一个空目录似乎是最小阻力的路径,因为你有脚本期望该目录存在(可能是因为它是生成二进制文件的目标)。另一种方法是修改脚本以根据需要创建目录。
mkdir --parents .generated/bin ## create a folder for storing generated binaries
mv myprogram1 myprogram2 .generated/bin ## populate the directory as needed
在此示例中,您可以检入目录的(损坏的)符号链接,以便在没有<!> quot; .generated <!>的情况下访问它;前缀(但这是可选的)。
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
假设您需要一个名为 tmp 的空目录:
$ mkdir tmp
$ touch tmp/.gitignore
$ git add tmp
$ echo '*' > tmp/.gitignore
$ git commit -m 'Empty directory' tmp
换句话说,您需要先将.gitignore文件添加到索引中,然后才能告诉Git忽略它(以及空目录中的其他所有内容)。
我也一直面临着空目录的问题。使用占位符文件的问题是你需要创建它们,并删除它们,如果不再需要它们(因为后来有添加的子目录或文件。使用大源树管理这些占位符文件可能很麻烦和错误易发生。
这就是为什么我决定编写一个开源工具,它可以自动管理这些占位符文件的创建/删除。它是为.NET平台编写的,可在Mono(.NET for Linux)和Windows下运行。
你不能也不可能永远无法做到。这是Linus Torvald本人做出的决定。他知道什么对我们有好处。
在那里我读过一次咆哮。
我找到 Re:空目录...... ,但也许有另一个。
不幸的是,你必须忍受变通办法。
我喜欢@ Artur79和@mjs的答案,所以我一直在使用两者的组合,并使其成为我们项目的标准。
find . -type d -empty -exec touch {}/.gitkeep \;
但是,只有少数开发人员在Mac或Linux上工作。在Windows上做了很多工作,我找不到相同的简单单行程来完成相同的工作。有些人幸运的是因为其他原因安装了 Cygwin ,但是为此而开的Cygwin似乎有点矫枉过正。
编辑以获得更好的解决方案
因此,由于我们的大多数开发人员已经安装了 Ant ,我首先想到的是整合一个Ant构建文件,以独立于平台完成此任务。这仍然可以在这里找到
然而,我后来认为将它变成一个小实用程序命令会更好,所以我使用Python重新创建它并将其发布到PyPI 这里。您只需运行以下命令即可安装:
pip3 install gitkeep2
它允许您递归地创建和删除.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.
我希望你觉得它很有用。
当您添加.gitignore
文件时,如果您要在其中放入任意数量的内容(您希望Git忽略),您可能希望添加一行只带星号*
以确保您不会意外添加被忽略的内容。
如前所述,不可能添加空目录,但这里有一个将空.gitignore文件添加到所有目录的单行程序。
ruby -e 'require "fileutils" ; Dir.glob(["target_directory","target_directory/**"]).each { |f| FileUtils.touch(File.join(f, ".gitignore")) if File.directory?(f) }'
我把它放在Rakefile中以便于访问。
Jamie Flournoy的解决方案效果很好。这是一个保持.htaccess
:
# Ignore everything in this directory
*
# Except this file
!.gitignore
!.htaccess
使用此解决方案,您可以提交一个空文件夹,例如/log
,/tmp
或/cache
,文件夹将保持为空。
我总是构建一个函数来检查我想要的文件夹结构,并在项目中为我构建它。这解决了这个问题,因为空文件夹由代理保存在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中,但我确信大多数语言都支持相同的功能,并且由于应用程序负责创建文件夹,因此文件夹将始终存在。
这里是一个黑客,但它很有趣,它的工作(Git2.2.1).类似什么@特卡建议,但更容易记住:
- 增加一个子模块的任何库(
git submodule add path_to_repo
) - 这将增加一个文件夹和一个文件
.submodules
.提交的变化。 - 删除
.submodules
文件和提交的变化。
现在,你有一个目录,得到创造当提交被检查出来。一个有趣的事情但是如果你看一下内容的树目的这个文件,你会得到:
致命的:没有一个有效的对象的名字 b64338b90b4209263b50244d18278c0999867193
我不鼓励使用它,虽然因为它可能会停止工作,在未来版本的饭桶。这可能会离开你的仓库损坏。
没有办法让Git跟踪目录,所以唯一的解决方案是在你希望Git跟踪的目录中添加一个占位符文件。
该文件可以命名并包含您想要的任何内容,但大多数人使用名为.gitkeep
的空文件(尽管有些人更喜欢与VCS无关的.keep
)。
带前缀的.
将其标记为隐藏文件。
另一个想法是添加一个README
文件,解释目录的用途。
你做不到。这是Git维护者的故意设计决定。基本上,像Git这样的源代码管理系统的目的是管理源代码,而空目录不是源代码。 Git也经常被描述为内容跟踪器,同样,空目录不是内容(实际上完全相反),因此不会跟踪它们。
如果你想在多个语义目录中添加一个容纳大量瞬态数据的文件夹,那么一种方法就是将这样的东西添加到你的root .gitignore ......
/app/data/**/*.*
!/app/data/**/*.md
然后你可以在每个目录中提交描述性的README.md文件(或空白文件,无关紧要,只要你可以像在这种情况下那样唯一地定位它们),以确保所有目录都保留repo的一部分,但文件(带扩展名)将被忽略。限制:目录名称中不允许*.md
!
您可以使用xml / images文件或其他任何内容填充所有这些目录,并随着时间的推移在.
下添加更多目录,因为您的应用程序的存储需求正在开发中(README.md文件用于描述每个存储目录的确切含义。
通过为每个新目录创建新的/app/data/
,无需进一步更改.gitignore
或分散。可能不是最聪明的解决方案,但是简洁明了,总是适合我。好又简单! ;)
为战斗添加一个选项。
假设您想要添加一个目录git
,为了与.gitignore
相关的所有目的,应该保持为空并且永远不会跟踪它的内容,这里建议多次*
如上所述,格式为:
*
!.gitignore
现在,如果你想在命令行中做一个方法,一下子, inside 你要添加的目录,你可以执行:
$ echo "*" > .gitignore && echo '!.gitignore' >> .gitignore && git add .gitignore
我自己,我有一个用于执行此操作的shell脚本。无论你想要什么,都要命名脚本,并将其添加到include路径中的某个位置,或者直接引用它:
#!/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 将来包含跟踪文件的空文件夹,但现在是空的,你可以省略来自<=>文件的<=>,并检查那个。基本上,所有文件都是<!>;不要忽略 me <!> “;否则,该目录为空并进行跟踪。
您的<=>文件如下所示:
!.gitignore
就是这样,检查一下,你有一个空的,但跟踪的目录,你可以在以后跟踪文件。
我建议在文件中保留一行的原因是它给出了<=>目的。否则,某些人可能会认为将其删除。如果您在该行上方发表评论可能会有所帮助。
有时你必须处理糟糕的书面库或软件,这需要一个<!> quot; real <!> quot;空和现有目录。使用简单的.gitignore
或.keep
可能会破坏它们并导致错误。以下可能有助于这些情况,但不保证......
首先创建所需的目录:
mkdir empty
然后你向这个目录添加一个破损的符号链接(但除了上面描述的用例之外的任何其他情况,请使用带有解释的README
):
ln -s .this.directory empty/.keep
要忽略此目录中的文件,可以将其添加到根<=>:
中echo "/empty" >> .gitignore
要添加被忽略的文件,请使用参数强制它:
git add -f empty/.keep
提交后,索引中的符号链接断开,git会创建目录。断开的链接有一些优点,因为它不是常规文件,并且指向没有常规文件。所以它甚至适合问题<!>“;(不包含文件)<!>”的部分,不是出于意图而是出于意思,我猜:
find empty -type f
此命令显示空结果,因为此目录中不存在任何文件。因此,获取目录中所有文件的大多数应用程序通常都看不到此链接,至少如果它们存在<!>“文件存在<!>”;或者<!>“是可读的<!>”;甚至一些脚本也找不到任何文件:
$ php -r "var_export(glob('empty/.*'));"
array (
0 => 'empty/.',
1 => 'empty/..',
)
但我强烈建议仅在特殊情况下使用此解决方案,在空目录中编写好的<=>通常是更好的解决方案。 (我不知道这是否适用于Windows文件系统...)
您可以将此代码保存为create_readme.php,并从根目录运行 PHP 代码你的Git项目。
> php create_readme.php
它会将README文件添加到所有空目录中,这样这些目录就会被添加到索引中。
<?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
有时我的文件夹存储库只包含被认为是<!>的文件<!>内容<!> <!>#!>#8212;也就是说,它们不是我关心版本化的文件,并且因此永远不应该犯下。使用Git的.gitignore文件,您可以忽略整个目录。但有时候在回购中使用文件夹会有所帮助。这是满足这一需求的出色解决方案。
我过去所做的是在我的仓库的根目录下放一个.gitignore文件,然后排除文件夹,如下所示:
/app/some-folder-to-exclude
/another-folder-to-exclude/*
然而,这些文件夹不会成为回购的一部分。您可以在其中添加类似README文件的内容。但是,您必须告诉您的应用程序不要担心处理任何README文件。
如果您的应用依赖于那里的文件夹(虽然是空的),您只需将.gitignore文件添加到相关文件夹中,然后使用它来完成两个目标:
告诉Git文件夹中有一个文件,这使得Git将它添加到repo中。 告诉Git忽略此文件夹的内容,减去此文件本身。 这是放在空目录中的.gitignore文件:
*
!.gitignore
第一行(*)告诉Git忽略此目录中的所有内容。第二行告诉Git不要忽略.gitignore文件。您可以将此文件填充到要添加到存储库的每个空文件夹中。
一种简单的方法是将.gitkeep
文件添加到您希望(当前)保持为空的目录中。
有关详细信息,请参阅此 SOF答案 - 这也解释了为什么有些人会发现添加.gitignore的竞争惯例文件(如许多答案中所述)令人困惑。