如何将空目录(不包含文件)添加到Git存储库?
使目录保持(几乎)为空(在存储库中)的另一种方法是.gitignore
在该目录中创建一个包含以下四行的文件:
# Ignore everything in this directory * # Except this file !.gitignore
然后,您不必按照m104 解决方案中的方式完成订单.
这样做的好处是,当你执行git状态时,该目录中的文件不会显示为"未跟踪".
让@GreenAsJade的评论持久:
我认为值得注意的是,这个解决方案确切地解决了问题所要求的问题,但也许不是很多人在看这个问题时会想到的.此解决方案可确保目录保持为空.它说"我真的不想在这里检查文件".与"我这里没有任何要检查的文件相反,但我需要这里的目录,文件可能会在以后".
你不能.请参阅Git常见问题解答.
目前git索引(临时区域)的设计只允许列出文件,没有人能够进行更改以允许空目录已经足够关注这种情况来弥补它.
在其中添加文件时会自动添加目录.也就是说,目录永远不必添加到存储库中,并且不会自己跟踪.
你可以说"
git add
",它会在那里添加文件.如果您确实需要在结帐中存在目录,则应在其中创建一个文件..gitignore很适合这个目的; 您可以将其留空,或填写您希望在目录中显示的文件的名称.
创建一个.gitkeep
在目录中调用的空文件,然后添加它.
您始终可以在目录中放置一个README文件,并说明您为什么要在存储库中使用此目录(否则为空).
touch .keep
在Linux上,这会创建一个名为的空文件.keep
.这个名称是优先的,.gitkeep
因为前者对Git是不可知的,而后者是Git特有的.其次,正如另一位用户所说,.git
前缀约定应该保留给Git本身使用的文件和目录.
或者,如另一个答案中所述,目录可以包含描述符README
或README.md
文件.
当然,这要求文件的存在不会导致应用程序中断.
首先要做的事情:
空目录不能是Git版本控制系统下树的一部分.
它根本不会被跟踪.但是有些情况下"版本控制"空目录可能有意义,例如:
脚手架预定义的文件夹结构,使其可供存储库的每个用户/贡献者使用; 或者,作为上述的一个特例,为我们想要提供文件夹但其内容的临时文件(如a cache/
或logs/
目录)创建一个文件夹.gitignore
与上述相关,有些项目在没有一些文件夹的情况下将无法运行(这通常是一个设计不良的项目的暗示,但这是一个经常出现的现实场景,也许可能会有,例如,许可问题需要解决).
许多用户建议:
放置README
包含某些内容的文件或其他文件,以使目录非空,或
.gitignore
使用一种"反向逻辑"(即包括所有文件)创建一个文件,最后,它与方法#1的目的相同.
虽然两种解决方案确实有效,但我发现它们与Git版本化的有意义的方法不一致.
你为什么要把伪造的文件或自述文件放在你的项目中?
为什么要使用.gitignore
(保留文件)与其意图(文件除外)完全相反的东西,即使它有可能?
使用调用的空文件.gitkeep
以强制在版本控制系统中存在该文件夹.
虽然看起来没有那么大的区别:
您使用的文件具有保留文件夹的唯一目的.你没有把任何你不想放的信息放在那里.
例如,你应该使用自述文件作为有效信息的自述文件,而不是保留文件夹的借口.
关注点分离总是一件好事,您仍然可以添加一个.gitignore
来忽略不需要的文件.
命名它.gitkeep
使文件本身(以及其他开发人员,这对于共享项目和Git存储库的核心目的之一)非常清晰和直接,这个文件是
与代码无关的文件(因为前导点和名称)
一个与Git明显相关的文件
它的目的(保持)是明确陈述的,一致的和语义上的,其意思是忽略
我已经看到了.gitkeep
像Laravel,Angular-CLI这样非常重要的框架所采用的方法.
如其他答案中所述,Git无法在其临时区域中表示空目录.(请参阅Git常见问题解答.)但是,如果目录是空的,如果它只包含一个.gitignore
文件,那么.gitignore
只能通过以下方式在空目录中创建文件:
find . -type d -empty -exec touch {}/.gitignore \;
安迪·莱斯特是正确的,但如果你的目录只需要为空,而不是空的空的,你可以把一个空.gitignore
文件,在那里作为一种解决方法.
顺便说一下,这是一个实现问题,而不是基本的Git存储设计问题.正如在Git邮件列表中多次提到的那样,没有实现这一点的原因是没有人关心为它提交补丁,而不是它不能或不应该完成.
在Ruby on Rails的日志文件夹的创建方式:
mkdir log && touch log/.gitkeep && git add log/.gitkeep
现在日志目录将包含在树中.它在部署时非常有用,因此您不必编写例程来创建日志目录.
可以通过发出来保留日志文件,
echo log/dev.log >> .gitignore
但你可能知道这一点.
Git不跟踪空目录.有关更多说明,请参阅Git FAQ.建议的解决方法是将.gitignore
文件放在空目录中.我不喜欢这个解决方案,因为它.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文件之外的目录中的所有内容,请在以下行中添加以下行.gitignore
:
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
要在每个README创建后列出它们:
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]路径(选项卡很重要,答案格式不保留它).
而已!您的空文件夹位于索引中.你所要做的就是提交.
这个解决方案很短,显然工作正常(参见编辑!),但它并不容易记住......
空树SHA-1可以通过创建一个新的空Git存储库找到cd
它并发出git write-tree
,它输出空树SHA-1.
编辑:
自从我找到它以来,我一直在使用这个解决方案.它似乎与创建子模块的工作方式完全相同,只是在任何地方都没有定义模块.这会在发布时导致错误git submodule init|update
.问题是git update-index
将040000 tree
部分重写为160000 commit
.
此外,放在该路径下的任何文件都不会被Git注意到,因为它认为它们属于某个其他存储库.这很讨厌,因为它很容易被忽视!
但是,如果您尚未(并且不会)在存储库中使用任何Git子模块,并且"empty"文件夹将保持为空或者您希望Git知道其存在并忽略其内容,则可以使用这个调整.以子模块的常规方式采取更多步骤进行调整.
假设您需要一个名为tmp的空目录:
$ mkdir tmp $ touch tmp/.gitignore $ git add tmp $ echo '*' > tmp/.gitignore $ git commit -m 'Empty directory' tmp
换句话说,您需要将.gitignore文件添加到索引中,然后才能告诉Git忽略它(以及空目录中的其他所有内容).
也许添加一个空目录似乎是阻力最小的路径,因为你有脚本期望该目录存在(可能因为它是生成二进制文件的目标).另一种方法是修改脚本以根据需要创建目录.
mkdir --parents .generated/bin ## create a folder for storing generated binaries mv myprogram1 myprogram2 .generated/bin ## populate the directory as needed
在此示例中,您可以检入目录的(损坏的)符号链接,以便您可以在不使用".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
我也一直面临空目录的问题.使用占位符文件的问题是你需要创建它们,并删除它们,如果不再需要它们(因为后来有添加的子目录或文件.使用大源树管理这些占位符文件可能很麻烦和错误易于.
这就是为什么我决定编写一个开源工具,可以自动管理这些占位符文件的创建/删除.它是为.NET平台编写的,可在Mono(.NET for Linux)和Windows下运行.
请查看:http://code.google.com/p/markemptydirs
我喜欢@ 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.
希望对你有帮助.
你不能,不幸的是永远不会.这是Linus Torvald本人做出的决定.他知道什么对我们有好处.
在那里我读过一次咆哮.
我找到了Re:Empty目录..但也许还有另一个.
你不得不忍受变通办法......不幸的是.
当你添加一个.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跟踪目录,所以唯一的解决方案是在你希望Git跟踪的目录中添加一个占位符文件.
该文件可以命名并包含您想要的任何内容,但大多数人使用一个名为空的文件.gitkeep
(尽管有些人更喜欢VCS不可知.keep
).
前缀将其.
标记为隐藏文件.
另一个想法是添加一个README
文件,解释目录将用于什么.
我总是构建一个函数来检查我想要的文件夹结构,并在项目中为我构建它.这解决了这个问题,因为空文件夹由代理保存在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中,但我确信大多数语言都支持相同的功能,并且由于应用程序负责创建文件夹,因此文件夹将始终存在.
这是一个黑客,但它很有趣(Git 2.2.1).与@Teka建议的类似,但更容易记住:
将子模块添加到任何存储库(git submodule add path_to_repo
)
这将添加一个文件夹和一个文件.submodules
.做出改变.
删除.submodules
文件并提交更改.
现在,您有一个在签出提交时创建的目录.一个有趣的事情是,如果你看看这个文件的树对象的内容,你会得到:
致命的:不是有效的对象名称b64338b90b4209263b50244d18278c0999867193
我不鼓励使用它,因为它可能会停止在Git的未来版本中工作.这可能会使您的存储库损坏.
如果你想在多个语义目录中添加一个容纳大量瞬态数据的文件夹,那么一种方法是在你的root .gitignore中添加这样的东西......
/app/data/**/*.*
!/app/data/**/*.md
然后,您可以*.md
在每个目录中提交描述性README.md文件(或空白文件,无关紧要,只要您可以像在本例中那样唯一地定位它们),以确保目录全部保留在repo的一部分但是文件(带扩展名)将被忽略.限制:.
目录名称中不允许使用!
您可以使用xml/images文件或其他任何内容填充所有这些目录,并/app/data/
随着时间的推移添加更多目录,因为您的应用程序需要开发存储(使用README.md文件来描述每个存储目录的用途)究竟).
没有必要.gitignore
通过.gitignore
为每个新目录创建一个新的来进一步改变或分散.可能不是最聪明的解决方案,但是简洁明了,总是适合我.好又简单!;)
许多人已经回答了这个问题。只需在此处添加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}
你不能 这是Git维护者的有意设计决定。基本上,像Git这样的源代码管理系统的目的是管理源代码,而空目录不是源代码。Git通常也被描述为内容跟踪器,同样,空目录也不是内容(实际上恰恰相反),因此它们不会被跟踪。
一种简单的方法是将.gitkeep
文件添加到您希望(当前)保持空白的目录中。
请参阅此SOF答案以获取更多信息-这也解释了为什么有些人发现添加.gitignore文件的竞争惯例(如此处许多答案所述)令人困惑。