我怎样才能添加一个空目录到Git仓库?

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

另一种使目录保持为空的方法是在该目录中创build一个包含四行的.gitignore文件:

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

那么你不必像m104的解决scheme那样去订购。

你不能。 查看Git常见问题 。

目前,git索引(登台区域)的devise只允许列出文件,没有人能胜任这个更改,以允许空目录已经足够关心这种情况来解决这个问题。

添加文件时自动添加目录。 也就是说,目录永远不必被添加到存储库,并且不会自行跟踪。

你可以说“ git add <dir> ”,它会在那里添加文件。

如果你真的需要一个目录在结帐中存在,你应该在其中创build一个文件。 .gitignore适合这个目的; 您可以将其保留为空,或者填写您希望在目录中显示的文件的名称。

在目录中创build一个名为.gitkeep的空文件,并添加该文件。

您可以随时在目录中放入一个README文件,并解释为什么要在存储库中使用这个空的目录。

 touch .keep 

在Linux上,这将创build一个名为.keep的空文件。 这个名字比.gitkeep.gitkeep因为前者对Git是不可知的,而后者则是Git特有的。 其次,正如另一个用户所指出的, .git前缀约定应该保留给Git自己使用的文件和目录。

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

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

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

在Git版本控制系统下,一个空目录不能成为树的一部分 。 但是在很多情况下,空目录可能是有用的,例如:

  • 为有用的项目文件夹build立一个预定义的文件夹结构 ,比如composer php软件包的vendor/文件夹,并且使这个结构可以供存储库的每个用户/贡献者使用; 或者,作为上述的一个特例,为临时文件 (如cache/ logs/目录)创build一个文件夹
  • 有些项目没有一些文件夹根本无法工作 (这往往是一个devise不佳的项目的暗示,但这是一个频繁的现实世界的情况,也许可能有,比如说,权限问题)。

一些build议的解决方法

许多用户build议:

  1. 放置一个README文件或其他文件与一些内容,以使目录非空,或
  2. 用一种“反向逻辑”创build一个.gitignore文件(也就是包含所有的文件),最后,这个文件的作用和方法#1是一样的。

尽pipe这两个解决scheme都能正常工作 ,但毫无疑问,我发现它们与Git版本控制的有意义的方法不一致。

  • 为什么你应该把虚假文件或自述文件,也许你不想在你的项目?
  • 为什么使用.gitignore做一件事情( 保持文件),这是与它的意义相反( 不包括文件),尽pipe它是可能的?

.gitkeep方法

使用名为.gitkeep文件来强制在版本控制系统中存在文件夹。

虽然看起来可能没有那么大的差别:

  • 您使用具有保留该文件夹的单一目的的文件。 你不要把那些你不想放的信息放在那里。

    例如,您应该使用README作为自述文件,而不是作为保留文件夹的借口。

    关注分离总是一件好事,你仍然可以添加一个.gitignore来忽略不需要的文件。

  • 命名它.gitkeep使得从文件名本身(以及其他开发者 ,这对于共享项目和Git仓库的核心目的之一来说)这个文件是非常清楚和直接的

    • 一个与代码无关的文件(因为前导点和名称)
    • 一个文件清楚地与Git相关
    • 它的目的( 保持 )是明确陈述和一致的和语义上相反的意思是忽略

采用

我已经看到了像Laravel , Angular-CLI这样非常重要的框架所采用的.gitkeep方法。

正如其他答案中所述,Git无法在其暂存区域中表示空目录。 然而,如果你的目的是一个目录是空的,如果它只包含一个.gitignore文件,那么你可以在空目录中创build.gitignore文件,只能通过:

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

Andy Lester是对的,但是如果你的目录只需要是空的,而不是空的空白的,你可以把一个空的.gitignore文件作为一个解决方法。

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

Ruby on Rails的方式:

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

现在日志目录将被包含在树中。 这在部署时非常有用,因此您不必编写例程来创build日志目录。

日志文件可以通过发布,

 echo log/dev.log >> .gitignore 

但是你可能知道这一点。

Git不跟踪空目录。 查看Git FAQ获取更多解释。 build议的解决方法是将.gitignore文件放在空目录中。 我不喜欢这个解决scheme,因为.gitignore被Unix约定“隐藏”了。 也没有解释为什么这些目录是空的。

我build议把一个README文件放在空目录下,解释为什么这个目录是空的,为什么需要在Git中进行跟踪。 就README文件而言,就Git而言,目录不再是空的。

真正的问题是为什么你需要在git中的空目录? 在编译/运行之前,你没有一些可以创build空目录的构build脚本吗? 通常当你真的需要git中的空目录时,这是有原因的。 所以你把这个原因放在README文件中。 这样其他开发人员知道为什么空目录需要在那里。 未来,您还将知道,当需要空目录的问题已经解决时,您可以删除空目录。

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

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

要在每个空目录中创build占位符README,请执行以下操作:

 find -name .git -prune -o -type d -empty -exec sh -c \ "echo this directory is intentionally left empty > {}/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 

在每个自述文件已经创build之后列出:

 find -name README.emptydir 

警告:这种调整是不是真的工作,因为它结果。 抱歉给你带来不便。

原文如下:

我在玩Git内部的过程中find了一个解决scheme!

  1. 假设你在你的仓库中。
  2. 创build你的空目录:

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

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

    input命令,然后input第二行。 按Enter ,然后按Ctrl + D来终止您的input。 注意:格式为[SPACE] types [SPACE] SHA-1hash [TAB]path(选项卡很重要,答案格式不保留)。

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

这个解决scheme很简单,显然工作正常( 见编辑! ),但它不是那么容易记住…

空树SHA-1可以通过创build一个新的空Git仓库, cd到它并发出git write-tree ,输出空树SHA-1来find。

编辑:

自从我find它以来,我一直在使用这个解决scheme。 它看起来与创build子模块的方式完全一样,只是没有模块在任何地方被定义。 这在发出git submodule init|update时会导致错误。 问题是, git update-index040000 tree部分重写为160000 commit

此外,任何放置在该path下的文件都不会被Git注意到,因为它认为它们属于某个其他存储库。 这很可怕,因为它很容易被忽视!

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

也许增加一个空目录看起来像是阻力最小path,因为你的脚本需要该目录的存在(也许是因为它是生成的二进制文件的目标)。 另一种方法是修改脚本以根据需要创build目录

 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 

如果您采用常用的build议方法来检查几乎为空的文件夹,那么在删除内容的同时也不会删除“.gitignore”文件。

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

 .generated 

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

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

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

我一直在用空目录来解决这个问题。 使用占位符文件的问题是你需要创build它们,并删除它们,如果它们不再是必要的(因为稍后会添加子目录或文件)。对于大型源代码树来说,pipe理这些占位符文件可能很麻烦并且出错俯卧。

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

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

你不能也不可能永远不能。 这是Linus Torvald本人做出的决定。 他知道我们有什么好处

那里有一个咆哮,我读了一次。

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

你不得不忍受解决方法…不幸的是。

当你添加一个.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中以方便访问。

我总是build立一个函数来检查我想要的文件夹结构,并在项目中为我构build它。 这解决了这个问题,因为空的文件夹通过代理保存在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中,但我相信大多数语言支持相同的function,并由于文件夹的创build由应用程序的照顾,文件夹将永远在那里。

没有办法让Git跟踪目录,所以唯一的解决方法是在你想要跟踪的目录中添加一个占位符文件。

该文件可以被命名并包含任何你想要的东西,但大多数人使用一个名为.gitkeep的空文件(尽pipe有些人更喜欢VCS不可知的.keep )。

前缀. 将其标记为隐藏文件。

另一个想法是添加一个README文件来解释这个目录将被用于什么目的。

Jamie Flournoy的解决scheme非常棒。 这是一个增强版本,以保持.htaccess

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

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

I like the answers by @Artur79 and @mjs so I've been using a combination of both and made it a standard for our projects.

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

However, only a handful of our developers work on Mac or Linux. A lot work on Windows and I could not find an equivalent simple one-liner to accomplish the same there. Some were lucky enough to have Cygwin installed for other reasons, but prescribing Cygwin just for this seemed overkill.

So, since most of our developers already have Ant installed, I put together a build file to accomplish this independently of the platform.

 <?xml version="1.0" encoding="ISO-8859-1"?> <project name="Gitkeep" basedir="." default="keep"> <!--Apply to all subdirs of this dir--> <target name="keep" description="-> Add a .gitkeep file to all empty subdir's of this dir."> <!--Create a ref to all the subdirs in the tree of this dir--> <dirset id="dirs.ref" dir="./" includes="**/*"/> <!--Create a list of the subdirs under this dir--> <property name="dirs.list" refid="dirs.ref" /> <!--For each subdir--> <for list="${dirs.list}" delimiter=";" param="dir"> <sequential> <!--If the subdir is empty this target will add a .gitkeep file to it--> <antcall target="gitkeep" inheritall="false"> <param name="dir" value="@{dir}"/> </antcall> </sequential> </for> </target> <!--Add a .gitkeep file to a directory if it's empty--> <target name="gitkeep" description="-> Add a .gitkeep file to a specific subdir of this dir. Use -Ddir=relative/path/to/dir"> <!--Create a ref of the files inside this dir--> <fileset dir="${dir}" id="contents.ref"/> <!--Create a path to the contents of this directory, ONLY if it's not empty--> <pathconvert refid="contents.ref" property="contents.path" setonempty="false"/> <if> <!--If the dir is empty create the .gitkeep file--> <not><isset property="contents.path"/></not> <then> <!--Create the .gitkeep file--> <echo message="Version this dir in Git even if its empty." file="./${dir}/.gitkeep" force="true" append="false"/> </then> </if> </target> </project> 

Now I can simply run

 ant -f gitkeep.xml 

And this creates a .gitkeep file in any empty subdir. Even on Windows 🙂 Note: This build file requires the Ant Contrib jar.

I continue to work on this concept here .

https://github.com/mig82/gitkeep

Here is a hack, but it's funny that it works (Git 2.2.1). Similar to what @Teka suggested, but easier to remember:

  • Add a submodule to any repository ( git submodule add path_to_repo )
  • This will add a folder and a file .submodules . Commit a change.
  • Delete .submodules file and commit the change.

Now, you have a directory that gets created when commit is checked out. An interesting thing though is that if you look at the content of tree object of this file you'll get:

fatal: Not a valid object name b64338b90b4209263b50244d18278c0999867193

I wouldn't encourage to use it though since it may stop working in the future versions of Git. Which may leave your repository corrupted.

你不能。 This is an intentional design decision by the Git maintainers. Basically, the purpose of a Source Code Management System like Git is managing source code and empty directories aren't source code. Git is also often described as a content tracker, and again, empty directories aren't content (quite the opposite, actually), so they are not tracked.

You can save this code as create_readme.php and run the PHP code from the root directory of your Git project.

 > php create_readme.php 

It will add README files to all directories that are empty so those directories would be then added to the index.

 <?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 

Adding one more option to the fray.

Assuming you would like to add a directory to git that, for all purposes related to git , should remain empty and never have it's contents tracked, a .gitignore as suggested numerous times here, will do the trick.

The format, as mentioned, is:

 * !.gitignore 

Now, if you want a way to do this at the command line, in one fell swoop, while inside the directory you want to add, you can execute:

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

Myself, I have a shell script that I use to do this. Name the script whatever you whish, and either add it somewhere in your include path, or reference it directly:

 #!/bin/bash dir='' if [ "$1" != "" ]; then dir="$1/" fi echo "*" > $dir.gitignore && \ echo '!.gitignore' >> $dir.gitignore && \ git add $dir.gitignore 

With this, you can either execute it from within the directory you wish to add, or reference the directory as it's first and only parameter:

 $ ignore_dir ./some/directory 

Another option (in response to a comment by @GreenAsJade), if you want to track an empty folder that MAY contain tracked files in the future, but will be empty for now, you can ommit the * from the .gitignore file, and check that in. Basically, all the file is saying is "do not ignore me ", but otherwise, the directory is empty and tracked.

Your .gitignore file would look like:

 !.gitignore 

That's it, check that in, and you have an empty, yet tracked, directory that you can track files in at some later time.

The reason I suggest keeping that one line in the file is that it gives the .gitignore purpose. Otherwise, some one down the line may think to remove it. It may help if you place a comment above the line.

Sometimes you have to deal with bad written libraries or software, which need a "real" empty and existing directory. Putting a simple .gitignore or .keep might break them and cause a bug. The following might help in these cases, but no guarantee…

First create the needed directory:

 mkdir empty 

Then you add a broken symbolic link to this directory (but on any other case than the described use case above, please use a README with an explanation):

 ln -s .this.directory empty/.keep 

To ignore files in this directory, you can add it in your root .gitignore :

 echo "/empty" >> .gitignore 

To add the ignored file, use a parameter to force it:

 git add -f empty/.keep 

After the commit you have a broken symbolic link in your index and git creates the directory. The broken link has some advantages, since it is no regular file and points to no regular file. So it even fits to the part of the question "(that contains no files)", not by the intention but by the meaning, I guess:

 find empty -type f 

This commands shows an empty result, since no files are present in this directory. So most applications, which get all files in a directory usually do not see this link, at least if they do a "file exists" or a "is readable". Even some scripts will not find any files there:

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

But I strongly recommend to use this solution only in special circumstances, a good written README in an empty directory is usually a better solution. (And I do not know if this works with a windows filesystem…)

Sometimes I have repositories with folders that will only ever contain files considered to be "content"—that is, they are not files that I care about being versioned, and therefore should never be committed. With Git's .gitignore file, you can ignore entire directories. But there are times when having the folder in the repo would be beneficial. Here's a excellent solution for accomplishing this need.

What I've done in the past is put a .gitignore file at the root of my repo, and then exclude the folder, like so:

 /app/some-folder-to-exclude /another-folder-to-exclude/* 

However, these folders then don't become part of the repo. You could add something like a README file in there. But then you have to tell your application not to worry about processing any README files.

If your app depends on the folders being there (though empty), you can simply add a .gitignore file to the folder in question, and use it to accomplish two goals:

Tell Git there's a file in the folder, which makes Git add it to the repo. Tell Git to ignore the contents of this folder, minus this file itself. Here is the .gitignore file to put inside your empty directories:

 * !.gitignore 

The first line (*) tells Git to ignore everything in this directory. The second line tells Git not to ignore the .gitignore file. You can stuff this file into every empty folder you want added to the repository.

If you want to add a folder that will house a lot of transient data in multiple semantic directories, then one approach is to add something like this to your root .gitignore…

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

Then you can commit descriptive README.md files (or blank files, doesn't matter, as long as you can target them uniquely like with the *.md in this case) in each directory to ensure that the directories all remain part of the repo but the files (with extensions) are kept ignored. LIMITATION: . 's are not allowed in the directory names!

You can fill up all of these directories with xml/images files or whatever and add more directories under /app/data/ over time as the storage needs for your app develop (with the README.md files serving to burn in a description of what each storage directory is for exactly).

There is no need to further alter your .gitignore or decentralise by creating a new .gitignore for each new directory. Probably not the smartest solution but is terse gitignore-wise and always works for me. Nice and simple! ;)

在这里输入图像描述