How can I add an empty directory to a Git repository?

后端 未结 30 2459
离开以前
离开以前 2020-11-21 04:52

How can I add an empty directory (that contains no files) to a Git repository?

相关标签:
30条回答
  • 2020-11-21 05:16

    You can't. 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.

    0 讨论(0)
  • 2020-11-21 05:18

    Why would we need empty versioned folders

    First things first:

    An empty directory cannot be part of a tree under the Git versioning system.

    It simply won't be tracked. But there are scenarios in which "versioning" empty directories can be meaningful, for example:

    • scaffolding a predefined folder structure, making it available to every user/contributor of the repository; or, as a specialized case of the above, creating a folder for temporary files, such as a cache/ or logs/ directories, where we want to provide the folder but .gitignore its contents
    • related to the above, some projects won't work without some folders (which is often a hint of a poorly designed project, but it's a frequent real-world scenario and maybe there could be, say, permission problems to be addressed).

    Some suggested workarounds

    Many users suggest:

    1. Placing a README file or another file with some content in order to make the directory non-empty, or
    2. Creating a .gitignore file with a sort of "reverse logic" (i.e. to include all the files) which, at the end, serves the same purpose of approach #1.

    While both solutions surely work I find them inconsistent with a meaningful approach to Git versioning.

    • Why are you supposed to put bogus files or READMEs that maybe you don't really want in your project?
    • Why use .gitignore to do a thing (keeping files) that is the very opposite of what it's meant for (excluding files), even though it is possible?

    .gitkeep approach

    Use an empty file called .gitkeep in order to force the presence of the folder in the versioning system.

    Although it may seem not such a big difference:

    • You use a file that has the single purpose of keeping the folder. You don't put there any info you don't want to put.

      For instance, you should use READMEs as, well, READMEs with useful information, not as an excuse to keep the folder.

      Separation of concerns is always a good thing, and you can still add a .gitignore to ignore unwanted files.

    • Naming it .gitkeep makes it very clear and straightforward from the filename itself (and also to other developers, which is good for a shared project and one of the core purposes of a Git repository) that this file is

      • A file unrelated to the code (because of the leading dot and the name)
      • A file clearly related to Git
      • Its purpose (keep) is clearly stated and consistent and semantically opposed in its meaning to ignore

    Adoption

    I've seen the .gitkeep approach adopted by very important frameworks like Laravel, Angular-CLI.

    0 讨论(0)
  • 2020-11-21 05:18

    WARNING: This tweak is not truly working as it turns out. Sorry for the inconvenience.

    Original post below:

    I found a solution while playing with Git internals!

    1. Suppose you are in your repository.
    2. Create your empty directory:

      $ mkdir path/to/empty-folder
      
    3. Add it to the index using a plumbing command and the empty tree SHA-1:

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

      Type the command and then enter the second line. Press Enter and then Ctrl + D to terminate your input. Note: the format is mode [SPACE] type [SPACE] SHA-1hash [TAB] path (the tab is important, the answer formatting does not preserve it).

    4. That's it! Your empty folder is in your index. All you have to do is commit.

    This solution is short and apparently works fine (see the EDIT!), but it is not that easy to remember...

    The empty tree SHA-1 can be found by creating a new empty Git repository, cd into it and issue git write-tree, which outputs the empty tree SHA-1.

    EDIT:

    I've been using this solution since I found it. It appears to work exactly the same way as creating a submodule, except that no module is defined anywhere. This leads to errors when issuing git submodule init|update. The problem is that git update-index rewrites the 040000 tree part into 160000 commit.

    Moreover, any file placed under that path won't ever be noticed by Git, as it thinks they belong to some other repository. This is nasty as it can easily be overlooked!

    However, if you don't already (and won't) use any Git submodules in your repository, and the "empty" folder will remain empty or if you want Git to know of its existence and ignore its content, you can go with this tweak. Going the usual way with submodules takes more steps that this tweak.

    0 讨论(0)
  • 2020-11-21 05:18

    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.

    0 讨论(0)
  • 2020-11-21 05:19
    touch .keep
    

    On Linux, this creates an empty file named .keep. For what it's worth, this name is agnostic to Git. Secondly, as another user has noted, the .git prefix convention can be reserved for files and directories that Git itself uses for configuration purposes.

    Alternatively, as noted in another answer, the directory can contain a descriptive README.md file instead.

    Either way this requires that the presence of the file won't cause your application to break.

    0 讨论(0)
  • 2020-11-21 05:20

    When you add a .gitignore file, if you are going to put any amount of content in it (that you want Git to ignore) you might want to add a single line with just an asterisk * to make sure you don't add the ignored content accidentally.

    0 讨论(0)
提交回复
热议问题