4623

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

jub0bs
  • 46,795
  • 22
  • 148
  • 157
Laurie Young
  • 129,506
  • 13
  • 44
  • 54
  • 18
    While it's not useful, [there is a way to hack an empty (really empty) directory into your repo](http://stackoverflow.com/questions/11600871/git-repo-contains-an-empty-directory-what-happens/11600882#11600882). It won't `checkout` with current versions of Git, however. – tiwo Jul 22 '12 at 14:18
  • 376
    @tiwo I for one disagree that it's not useful. Your directory hierarchy is part of your project, so it should be version controlled. – JBentley Jan 29 '13 at 20:19
  • 4
    @JonBentley sure you are right! It's a pity that git fails to respect this part - but as long as this isn't fixed, it is useless to have empty directories in a repository (note that git ignores empty directories when checking out as well) – tiwo Feb 05 '13 at 22:35
  • 133
    In my case, I'd like to add a directory structure for tmp files, but not the tmp files themselves. By doing this, my tester has the correct structure (otherwise there are errors) but I don't clog my commits with tmp data. So yes, it's useful to me! – Adam Marshall Mar 13 '13 at 03:32
  • 47
    @AdamMarshall I think tiwo was saying that the hack is not useful, since it is ignored by checkout. Tmp dirs do sound like a useful feature for a VCS. – Quantum7 Apr 22 '13 at 21:33
  • 31
    Why not have the procedure that creates the tmp files also create the tmp directory? – RyPeck Jul 09 '13 at 03:11
  • 2
    You could probably use a [githook](http://git-scm.com/docs/githooks) or [gitattribute filter](http://git-scm.com/docs/gitattributes) to have a `.deleteme` file added to the repo that on checkout gets removed automatically. It will however probably break `git commit -a` and potentially be triggered on _every_ checkout... – Tobias Kienzler Aug 06 '13 at 14:58
  • 10
    To me, an upvote count of way over 1000 indicates that this feature should be within Git, as it is within SVN. Next, I know of at least one Software product which expects a certain folder structure to be present, even if some of these folders are actually empty. If I put an `.whatever` file in that folder, the file will become an (unwanted) part of my project, because that's the way this MF works. That has been a real pain with CVS and I really hoped these dark days were long forgotten. – JensG May 05 '14 at 10:56
  • 4
    @JensG 1000 upvotes means 1000 people find the question useful. And even if they all wanted the feature it does not mean it should be implemented---how many git users are there? – Alois Mahdal Nov 28 '14 at 17:46
  • 5
    To those people who think this isn't a useful feature, I would issue this challenge question: I have a /temp directory that needs to be "there" when the user checks things out. The software package I'm using does not create it if it's not there. How would I do this if not via having git recognijze an empty directory. – DaBlick Apr 20 '16 at 14:30
  • You can't. [Just create an empty file, such as `.keep`, in the directory.](https://stackoverflow.com/a/29884569/405550) – Zaz Feb 27 '17 at 14:52
  • I propose to add this to the main solution: https://stackoverflow.com/a/21422128/1670956 – Áxel Costas Pena Jun 14 '18 at 11:59
  • 1
    As required targets for future file creation under various permission schemes, empty folders are clearly useful. – Rick O'Shea Feb 14 '20 at 16:56

36 Answers36

4519

Another way to make a directory stay (almost) empty (in the repository) is to create a .gitignore file inside that directory that contains these four lines:

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

Then you don't have to get the order right the way that you have to do in m104's solution.

This also gives the benefit that files in that directory won't show up as "untracked" when you do a git status.

Making @GreenAsJade's comment persistent:

I think it's worth noting that this solution does precisely what the question asked for, but is not perhaps what many people looking at this question will have been looking for. This solution guarantees that the directory remains empty. It says "I truly never want files checked in here". As opposed to "I don't have any files to check in here, yet, but I need the directory here, files may be coming later".

HelloGoodbye
  • 2,752
  • 6
  • 32
  • 43
Jamie Flournoy
  • 47,204
  • 1
  • 21
  • 11
  • 30
    I think the README solution proposed by @JohnMee should be used together with this one; the .gitignore file provides an explanation of what we want to keep out of version control, while the README file explains what is the purpose of the directory, which are both very important pieces of information. – pedromanoel Jan 17 '13 at 11:11
  • 22
    @pedromanoel I write the documentation you would put in the `README` inside the `.gitignore` file (as comments). – Carlos Campderrós Jul 19 '13 at 08:20
  • 3
    The problem with "Just add a README" solution is that many times an application is descending into the directory and setting values from (temporary) files that are put in this otherwise empty directory. I like the idea of actually forcing git to keep it empty since this may be what the application wants/needs. – Andrew Oct 02 '13 at 13:13
  • 4
    This is great for out-of-source builds where you don't want to check in any binaries but don't want to have the user create the folder manually (in case your build system can't handle that). – Thomas Dec 14 '13 at 06:17
  • 81
    spot the 1 difference: 1.) an empty folder, 2.) a folder with .gitignore file in it. ;-) – Peter Perháč Feb 11 '14 at 14:31
  • 2
    @CarlosCampderrós came here to say that as well! I put a .gitignore into the empty directory with one comment "# this empty directory needs to be checked into git". This answer could pose problems when you actually want to put something into the directory and forget about your clever .gitignore instructions. – Matt K Feb 12 '14 at 21:07
  • 9
    This is perfect for *cache* folders. – redolent Mar 26 '14 at 02:30
  • 2
    While good advice - There is no need to ignore the file itself - either create the file and force add it (`echo "*" > .gitignore; git add -f .gitignore;`) or add the file and edit it (`touch .gitignore; git add .gitignore; echo "*" > .gitignore). This removes the somewhat pointless "but don't ignore the .gitignore" rule. – AD7six Jun 22 '14 at 13:17
  • 4
    @GreenAsJade If I understand the answer properly, this does not do precisely what the OP wanted. This creates a directory with one file in it, not an empty directory. In my case, I'm wanting an empty directory. – lmat - Reinstate Monica Aug 28 '14 at 18:10
  • 1
    "Empty **in the repo**". In your working copy, yes, you have the .gitignore file. Most people consider .git-something files to be "not there" for working purposes: IE for all intents and purposes it's considered an empty directory. – GreenAsJade Aug 29 '14 at 10:43
  • 1
    This what I need. Thanks. I just need a 'log' folder to put logging file, but I do not want to add any of these log files in git. PHP throws an error if the directory does not exist. – shrekuu Oct 13 '14 at 05:22
  • 16
    Unfortunately, this results in a non-empty directory, it has a single hidden file. – pedorro Dec 15 '14 at 20:09
  • 1
    @GreenAsJade, but when you add files later, you probably *want* to delete this placeholder .gitignore. And when you do that, the files are tracked. I'm not saying your point is wrong, just a real edge case. – Paul Draper Aug 29 '15 at 15:15
  • 2
    Typically, the point of a directory is to contain files. If you want to add an empty directory to a repository, it will probably eventually contain files, at least in one of the repositories or releases out there. But you probably don't want those files to be part of the repository, otherwise it would likely already contain one or more of those files or you could just wait until you add them. So for the primary case where you actually want an "empty" directory in the repository, this solution is perfect. – still_dreaming_1 Oct 26 '15 at 17:27
  • 1
    There is no need to put anything in .gitignore. Just check-in empty .gitignore. Many folders may get populated in future and the method in this answer will never add any files. So I would use this answer's approach very cautiously. – Shital Shah May 27 '16 at 21:58
  • 3
    @GreenAsJade Actually, it doesn't do *precisely* what was asked for, as the directory *isn't empty*. And as other users suggested, it's a bad idea to prefix with "git" as it's misleading---this is not a "git aware" strategy. – EntangledLoops Aug 03 '16 at 19:54
  • Although adding the .gitignore does guarantee that the directory remains empty, as soon as you have a file to commit you can just delete the .gitignore. It's simple and easy enough. – skullkid Dec 12 '16 at 01:30
  • This is the best solution to this to the question as by design git doesn't allow you to store empty folders and .gitignore can make sure that it stays empty. – Ketan Yekale Aug 21 '18 at 02:22
  • 1
    @GreenAsJade Yes good point, but sometimes this is exactly what is required. In My case this is for WordPress Plugins' cache folders (which need to exist as errors are thrown otherwise but you never ever want to commit any cache file). – Blackbam Aug 21 '18 at 12:42
  • 1
    @GreenAsJade What? It is definitely not considered an an empty directory for all intents and purposes! For example, a Python script will see this file if it looks for files in the folder, why the presence of a `.gitignore` file may make a significant difference. – HelloGoodbye Nov 20 '18 at 08:40
  • 1
    Almost empty ≠ empty. Question author asked about empty directories, and you should have assumed that they had a very good reason for that. – Szczepan Hołyszewski Dec 05 '19 at 02:33
  • Would you not need to replace `!.gitignore` with `!/.gitignore` to make sure other .gitignore files that you could eventually find in the ignored folder subtree are also ignored? – Héctor Jun 04 '20 at 16:25
  • mr Flournoy you are genius thank you! – Alex M.M. Dec 07 '20 at 11:53
  • Genius thanks a bunch – Hvitis May 27 '21 at 22:53
1132

You can't. See the Git FAQ.

Currently the design of the git index (staging area) only permits files to be listed, and nobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it.

Directories are added automatically when adding files inside them. That is, directories never have to be added to the repository, and are not tracked on their own.

You can say "git add <dir>" and it will add files in there.

If you really need a directory to exist in checkouts you should create a file in it. .gitignore works well for this purpose; you can leave it empty, or fill in the names of files you expect to show up in the directory.

Gilles 'SO- stop being evil'
  • 92,660
  • 35
  • 189
  • 229
Andy Lester
  • 81,480
  • 12
  • 93
  • 144
  • 74
    Below answer is MUCH better. The fact that git the low level software doesn't allow it doesn't matter to me as much as HOW to actually use Git when I need an empty directory. Adding a 2 line .gitignore seems acceptable to me. – Amala Apr 26 '11 at 15:21
  • 1
    Well if one want to move files into a new directory, they can't do it through `git mv` as git will complain that new directory is not under version control – lulalala Nov 02 '11 at 02:58
  • 16
    You can read "_it's impossible, you can't, etc._" all over the Internet for this frequent question. The `.gitignore` trick is a frequent answer, and satisfies many needs. However **it IS possible** to make git track an **truly empty** directory, [see my answer](http://stackoverflow.com/questions/115983/how-do-i-add-an-empty-directory-to-a-git-repository/8944077#8944077) – ofavre Jan 21 '12 at 15:44
  • 2
    Though the more I think of it, the more it feels like "SHA hash of the empty string", if it exists, actually _would_ be a well-defined identifier for an empty tree, unless it would be impossible to tell whether that object is a tree or a blob. – Emil Lundberg Jul 09 '13 at 09:47
  • 1
    thanks for adding the excerpt from the FAQ. It answers perfectly a question which I had recently. the .gitignore provides a better option than what I'd done, which was just adding an empty file. At least .gitignore is more indicative of purpose. – Matt Setter Sep 26 '13 at 15:07
  • 23
    I've seen a lot of repos that use an empty file called `.gitkeep` for this purpose. – Sukima Nov 13 '13 at 01:38
  • 1
    Ugh, this is so frustrating that Git can't properly handle empty directories! I'm hacking in the ugly .gitkeep, but I also need exclusions for all files, so I have to exclude .gitkeep from the exclusions! Such ugly hacks for what should be simple... – Brian Knoblauch Jul 03 '17 at 13:48
  • 1
    @Amala: what are you referring to, when you say "below". The order of answers is changing... – Thomas Weller Dec 11 '17 at 12:42
  • This should be the accepted answer. You simply can not store an empty directory in git. – axiopisty Jun 21 '19 at 01:32
  • You *can* actually add empty directories to a GIT repo without confusing the hack out of GIT + associated tools, [by “technically playing by the rules” while doing so](https://stackoverflow.com/a/58543445/277882)! The solution of course still involves submodules, but they only serve as a placeholder to make stuff look legit to tooling. – ntninja Oct 24 '19 at 14:45
888

Create an empty file called .gitkeep in the directory, and add that.

Mark Amery
  • 110,735
  • 57
  • 354
  • 402
Artur79
  • 10,574
  • 1
  • 20
  • 22
  • 69
    I have added an [answer](http://stackoverflow.com/a/21422128/832230) encouraging to create `.keep` instead. – Acumenus Jan 29 '14 at 04:31
  • 234
    `.gitkeep` has not been prescribed by Git and is going to make people second guess its meaning, which will lead them to google searches, which will lead them here. The `.git` prefix convention should be reserved for files and directories that Git itself uses. – t-mart Feb 10 '14 at 01:44
  • 10
    @t-mart "The `.git` prefix convention should be reserved..." Why? Does git request this reservation? – lmat - Reinstate Monica Aug 28 '14 at 18:13
  • 13
    In this case a `README` or `ABOUT` file would be just as good or better. Leaving a note for the next guy, just like we all used to do it before URLs. – Dave Nov 15 '14 at 00:59
  • 8
    Doesn't work if you're writing a unit test that should test code on an empty directory... – thebjorn Dec 23 '15 at 10:22
  • 5
    @szablica I don't think it's confusing at all. In fact I think it's very intuitive to call it .gitkeep. Calling it .gitignore is what sounds contradictory to me. So this is just a matter of personal taste. – Mig82 May 15 '17 at 18:17
  • 2
    @szablica, every thing is confusing to someone ¯\\_(ツ)_/¯ – tjfwalker Mar 13 '18 at 19:52
  • 1
    The reasons to use `.keep` are very good. A good balance between simple and less confusing. See the other answer http://stackoverflow.com/a/21422128/832230 If you have adopted the .gitkeep habit, run this over your repository: `git mv .gitkeep .keep` – mit Oct 29 '18 at 13:49
  • Usually use .empty or .keep – David K Nov 13 '19 at 10:09
  • `.emptydir` can be less confusing than `.gitkeep`. – Victor Yarema Nov 15 '19 at 13:07
  • you can create this file in windows using this command `echo>.gitkeep` – Mohamad Shiralizadeh Apr 16 '20 at 12:50
  • Whether you like the naming convention or not, this solution is one I've seen in more than one shop. – Owen S. Jun 20 '20 at 18:44
  • This one is the best method. The only argument I see around here is that .gitkeep in not documented. Guys, just use an empty .gitignore and add it. Your folder will be tracked and also delete proof in a sense that git status will show the missing tracked .gitignore file in case the folder does not exist anymore. – valiD Jun 25 '20 at 08:56
482

You could always put a README file in the directory with an explanation of why you want this, otherwise empty, directory in the repository.

Will
  • 21,498
  • 11
  • 84
  • 98
John Mee
  • 44,003
  • 31
  • 133
  • 171
  • 43
    +1, Good suggestion, an empty directory does not make any sense unless it is going to be used in the future. So create a README file inside it and write what this directory is for, and what files will be put there in the future. That solves both two problems. – saeedgnu Apr 04 '11 at 12:08
  • 2
    I agree. Empty folders are annoying and should be explained in all properly handled repositories of any kind. –  Aug 25 '11 at 03:37
  • 71
    @ilius Nonsense. A directory structure containing empty directories may be highly desirable in many situations (like an MVC app where you want a models directory but haven't gotten around to creating any models yet, or a shared views directory you plan to add shared views to, later). Moreover, putting a README in each one of these is overkill as it's obvious what they're there for, and it's easy to forget to put a README in each one of them. AND you have to remember to remove the README when you add some other files to them. Basically, git should definitely allow empty directories. – Jez Nov 21 '12 at 11:35
  • 22
    @Jez: I disagree. The point is that git is designed to control (and index) source-code. Importantly, the id of a commit is a hash of the contents. That is to say, it must have contents. You don't need a README in *every* part of the tree, only leaf nodes. If you have places you intend to put code, but no code, and you won't even take the time to echo "place for models" >> README, then what you have is an idea not a commit. It is not of interest to git. Saying "I want the running app to have XYZ empty directories" is a *runtime* problem, not a source problem. Handle it w/ your installer. – Joe Atzberger May 23 '13 at 00:36
  • @JoeAtzberger What about web applications? Should I give the web/application server permission to create the directories whenever they're missing? That's a strong security problem and a small performance issue to keep checking. Should I create a web app that needs special code run (e.g. create cache folder) in addition to a git clone? Now I need to add a readme, an install script and time to deal with everyone who doesn't bother to look at anything, expecting it to just work. There are even times when a directory tree with no files is something that gets used in a build/install process. – jbo5112 Jun 04 '13 at 21:04
  • 9
    @JoeAtzberger It's a missing feature, not an intentional limitation. From the Git FAQ: Currently the design of the Git index (staging area) only permits files to be listed, and **nobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it.** – jbo5112 Jun 04 '13 at 21:08
  • 8
    @jbo5112 Yes, the "special code" you refer to is the "installer" I mentioned. Your webapp installation already has to handle creating a database, local config, pulling dependencies or 100 other operations, but a couple empty directories are beyond it? Try gradle, passenger, chef, a primitive Makefile, etc. There is no security difference between creating directories and the other (potentially far more complicated/dangerous) work of installing an app. And if you really have no deps, config, DB, etc., and no installer, then just use the README. No case requires you to do both. – Joe Atzberger Jun 19 '13 at 22:46
  • Your FAQ citation says it is the design. It describes the current state of the code (w/o the feature). It also says of all the many git contributors, none of them care enough to change it. I would say that also characterizes their "intent" more than any feature wishlist. You may contemplate the people who wrote the best version control in the world, the one we freely enjoy: are they *crazy*? *mean*? *incompetent*? or do they maybe just understand this differently? – Joe Atzberger Jun 19 '13 at 22:57
  • 1
    @JoeAtzberger The way it appears to me is that it is a missing feature that isn't important enough for the maintainers to fix, because it would require a lot of redesign. Remember, git was built and deployed by Linus Torvalds in 2 weeks because he was frustrated with existing versioning. If it were a feature they intend to leave out, then the FAQ would probably say it's intentionally not allowed or "Permanently the design of the Git index," instead of having discussions on the mailing list about how to implement the feature that is not "Currently the design." – jbo5112 Jun 20 '13 at 17:07
  • My web-app case is that multiple short-term developers are pulling/cloning the code and hitting the same database (not ideal, but I have reasons). It has no installer; no managing of deps, config, etc.; no README. It has to stabilize and produce more installs first. Occasionally the code is pushed into production. On a separate project, I have server code that creates a lengthy directory structure (no files) with some complicated permissions for new customer accounts. This would be much easier to maintain by managing a template copy instead of code. Chef is overkill, and nothing else helps. – jbo5112 Jun 20 '13 at 17:30
  • 1
    @Jez why remove the READMEs? READMEs in directories besides just the root directory is very useful, especially when your repository is hosted on GitHub which automatically displays READMEs in every directory. – Dennis Feb 01 '14 at 21:52
  • I recommend to put a file named `PLACEHOLDER` instead of `README` for subdirectories. – eonil Nov 02 '14 at 23:04
  • This is the route i finally decided on I was thinking of this when i saw people saying about .gitkeep for my case this is the better solution in my opinion. Its for keeping folders like lib and obj which is apart of my build process. OK a readme is overkill for other developers but for people just starting, I certainly would of benefited from having readmes back when i started. I think it depends on the project and the way its going to be used. – Lightbulb1 Apr 09 '15 at 09:09
  • This should be the accepted answer to the question as it was asked. An impossibility result is a valuable result. It saves the time that would be wasted looking for a solution that does not exist. – Szczepan Hołyszewski Dec 05 '19 at 02:34
426
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.

Acumenus
  • 41,481
  • 14
  • 116
  • 107
  • 1
    This is good for an initial bare directory, but what if it starts to fill with files? Then Git will notice them and claim them as untracked files. The selected answer here works far more elegantly to allow one to keep a directory but then safely ignore the contents. – Giacomo1968 Sep 01 '14 at 16:20
  • 16
    The question and the predominant general concern is about adding an empty directory. If it later has a resident file, obviously delete the `.keep` file or just disregard it. If instead the files in the directory are to be ignored, that's a different question altogether. – Acumenus Sep 01 '14 at 21:30
  • 3
    It was suggested that `git clean -nd | sed s/'^Would remove '// | xargs -I{} touch "{}.keep"` will do this in all untracked empty directories. – Acumenus Oct 07 '14 at 17:16
  • 1
    Don't like this solution, it is tough to guess what this file does. Also, if you are generating files in your dev environment (like logs or images, etc.), this isn`t keeping those file from being versioned and making their way into production, which is not nice. – danielrvt May 19 '16 at 16:04
  • 1
    Windows doesn't like files without names and requires special magic to accomplish this (aka a bash-like terminal app or equivalent). – EntangledLoops Aug 03 '16 at 19:46
  • @A-B-B I'm aware, that's what I meant by "special magic". But regardless, this isn't a real solution, as the asker requested an "empty directory" and this isn't empty by definition. I actually want a *completely empty directory* for a particular use case and that isn't covered by git. – EntangledLoops Aug 04 '16 at 14:50
  • 2
    Elegant: the `.keep` file _together with the commit message_ shows the intent of "keeping" the project structure. Adding Readme or Abouts I think will cause more confusion... – Tanasis Oct 06 '17 at 10:39
  • The reasons to use `.keep` over `.gitkeep` are very good. A good balance between simple and less confusing. Namespaces seem important and it should not be broken that `.git....` looks like git's own file namespace. Additional documentation could go the projects global readme or coding style guides or a local readme. If you have adopted the .gitkeep habit, simply find the files and rename them: `git mv .gitkeep .keep`. Embrace change! The `.gitignore` solution recommended by the git documentation seems a hacky workaround and over complicated. – mit Oct 29 '18 at 13:54
  • 1
    On the other hand, the problem is very Git-dependent, as you wouldn't have this problem unless if it was because of the fact that you version control your project. – HelloGoodbye Nov 20 '18 at 08:48
334

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.

Manu Manjunath
  • 5,540
  • 1
  • 29
  • 30
Cranio
  • 8,964
  • 2
  • 29
  • 51
  • 9
    You missed one thought - whats the reason for keeping and empty folder (e.g. /logs, /tmp, /uploads)? Yes - its to keep the folder empty. :) So if you want to keep a folder empty, you have to ignore the files inside it. – Roman Oct 03 '14 at 00:08
  • 16
    @RomanAllenstein: not necessarily. It could be that you create a repo with a given structure which can become populated later. Those files will be added to the repo as soon as they are created, and it will be annoying to start deleting or editing .gitignore files (and dangerous, because probably you do not even realize that they are not being tracked: git is ignoring them) – blueFast Feb 17 '15 at 16:06
  • Another usecase: I keep my /etc in version control. Some directories there are empty, but I want to track them in my repo (they must be there, otherwise some tools will simply not work). But I do not want to ignore the files there: as soon as I `apt-get update ; apt-get upgrade` new files can appear, which I for sure do not want to ignore. – blueFast Feb 17 '15 at 16:08
  • 48
    @Behnam: I'll take the downvote, but my research on the S.O. meta shows no concern towards verbose answers, as long as they provide enough detail and clarity to be useful for every reader (and every skill level). Still I'm very open to any criticism and thank you for having declared the reason publicly, I take it very positively. – Cranio Oct 10 '16 at 13:22
  • 5
    If you edit your answer to replace `.gitkeep` with any other non git-prefixed file name you get my upvote, I think this one is the best and most informative answer. Reason: I think ".git*" should be reserved for git prescribed files, while this is just a mere placeholder. My first guess when I saw that is that for example a ".gitkeep" file would be auto-ignored (that would be a nice feature) but that is not the case, right? – Johnny Nov 21 '16 at 09:34
  • 1
    @Santosh You could edit my post and be useful to the community instead of childishly bragging against a non-native speaker and uselessly polluting the comments, which is [IN]consistent with average intelligent behaviour. That's why edits are for, btw. Thanks for the free lesson anyway, duly appreciated :) – Cranio Dec 09 '17 at 09:45
  • 1
    Thanks @Cranio for your excellent post, upvote. You can improve it by adding an option to just use .keep – danilo Jan 28 '18 at 01:50
  • 9
    I wonder why people have such a hard time to understand why one wants to add "empty" folders to git. You have to start somewhere, right? So, usually you start with your projects folder structure and - alas - at the start of the project there is nothing there yet. Once your project repo is done, team workers can clone and start working on the SAME structure. – BitTickler Oct 21 '18 at 02:36
130

As described in other answers, Git is unable to represent empty directories in its staging area. (See the Git FAQ.) However, if, for your purposes, a directory is empty enough if it contains a .gitignore file only, then you can create .gitignore files in empty directories only via:

find . -type d -empty -exec touch {}/.gitignore \;
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
mjs
  • 57,072
  • 26
  • 82
  • 114
  • 22
    You may want to ignore the .git directory: ``find . -name .git -prune -o -type d -empty -exec touch {}/.gitignore \;`` – steffen Aug 12 '13 at 12:51
  • 3
    A simpler variation for most situations is `find * -type d -empty -exec touch {}/.gitignore \;` – akhan Oct 24 '13 at 08:26
  • 2
    Since OS X creates a .DS_Store file in almost every directoy, this does not work there. The only (DANGEROUS!) workaround i found, was to delete all the .DS_Store files first via `find . -name .DS_Store -exec rm {} \;` and then use the preferred variant from this answer. Be sure to only execute this in the correct folder! – zerweck Apr 28 '15 at 15:57
  • 1
    Does anyone know a way to do this in Windows from the command line? I've seen some solutions here in Ruby and Python, but I'd like a barebones solution if it can be managed. – Mig82 Jan 03 '17 at 17:18
  • @zerweck You should have `.DS_Store` in `.gitignore`. See [this link](http://devoh.com/blog/2013/01/global-gitignore) on to set it up. – akhan Apr 05 '17 at 01:04
  • 1
    @akhan Adding something to `.gitignore` has no influence on the `-empty` flag of the `find` command. My comment is about removing the `.DS_Store` files in a directory tree, so the `-empty` flag can be applied. – zerweck Apr 06 '17 at 11:58
  • what about **find . -type d -empty -exec echo mkdir -p {} \; > make_empty_dirs.sh** and then commit make_empty_dirs.sh ? – grenix May 07 '21 at 06:26
71

Andy Lester is right, but if your directory just needs to be empty, and not empty empty, you can put an empty .gitignore file in there as a workaround.

As an aside, this is an implementation issue, not a fundamental Git storage design problem. As has been mentioned many times on the Git mailing list, the reason that this has not been implemented is that no one has cared enough to submit a patch for it, not that it couldn’t or shouldn’t be done.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Aristotle Pagaltzis
  • 101,052
  • 21
  • 94
  • 96
  • 4
    That's exactly what I said. Both paragraphs are addressed in the snippet of FAQ I posted. – Andy Lester Sep 22 '08 at 17:36
  • 1
    I think the aside is unteresting and useful to know -- it can be fixed, just don't expect it anytime soon when there's such an easy workaround for most cases. – wnoise Sep 22 '08 at 22:10
  • Sorry, I didn’t read the last paragraph, and while I did read the first paragraph, well, I’m not sure why I repeated that information. – Aristotle Pagaltzis Sep 23 '08 at 07:37
  • 2
    Of course, this extra answer does serve to point out the fact. – Michael Johnson Sep 24 '08 at 06:44
  • I got here looking at a case where the build fell down if the directory doesn't exist and by default it is empty, but it doesn't need to be empty. Creating a .gitignore does the right thing. – Joshua Apr 18 '16 at 16:25
32

The Ruby on Rails log folder creation way:

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

Now the log directory will be included in the tree. It is super-useful when deploying, so you won't have to write a routine to make log directories.

The logfiles can be kept out by issuing,

echo log/dev.log >> .gitignore

but you probably knew that.

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
Thomas E
  • 3,684
  • 2
  • 18
  • 13
31

Git does not track empty directories. See the Git FAQ for more explanation. The suggested workaround is to put a .gitignore file in the empty directory. I do not like that solution, because the .gitignore is "hidden" by Unix convention. Also there is no explanation why the directories are empty.

I suggest to put a README file in the empty directory explaining why the directory is empty and why it needs to be tracked in Git. With the README file in place, as far as Git is concerned, the directory is no longer empty.

The real question is why do you need the empty directory in git? Usually you have some sort of build script that can create the empty directory before compiling/running. If not then make one. That is a far better solution than putting empty directories in git.

So you have some reason why you need an empty directory in git. Put that reason in the README file. That way other developers (and future you) know why the empty directory needs to be there. You will also know that you can remove the empty directory when the problem requiring the empty directory has been solved.


To list every empty directory use the following command:

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

To create placeholder READMEs in every empty directory:

find -name .git -prune -o -type d -empty -exec sh -c \
  "echo this directory needs to be empty because reasons > {}/README.emptydir" \;

To ignore everything in the directory except the README file put the following lines in your .gitignore:

path/to/emptydir/*
!path/to/emptydir/README.emptydir
path/to/otheremptydir/*
!path/to/otheremptydir/README.emptydir

Alternatively, you could just exclude every README file from being ignored:

path/to/emptydir/*
path/to/otheremptydir/*
!README.emptydir

To list every README after they are already created:

find -name README.emptydir
lesmana
  • 22,750
  • 8
  • 73
  • 83
29

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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
ofavre
  • 3,558
  • 1
  • 24
  • 23
  • After putting the empty folder into the index and committing, is it then possible to `git svn dcommit` it with the desired result? – lmat - Reinstate Monica Aug 28 '14 at 18:16
  • 3
    It's unlikely that this tweak will work with any other tool. Like stated in the warning and the edit, I discourage using it unless in a quite restricted case. – ofavre Sep 02 '14 at 18:15
  • 1
    And of course this is why messing with the git internals is contraindicated. – Casey Jul 14 '15 at 20:34
  • I've created a better solution based on this that doesn't have these drawbacks: https://stackoverflow.com/a/58543445/277882 – ntninja Oct 24 '19 at 14:46
24

Let's say you need an empty directory named tmp :

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

In other words, you need to add the .gitignore file to the index before you can tell Git to ignore it (and everything else in the empty directory).

GAMITG
  • 3,670
  • 7
  • 30
  • 50
m104
  • 1,028
  • 6
  • 6
  • 12
    Two things: You could just "echo '*' > tmp/.gitignore" instead of touching, and "git commit -m" does not commit changes done after you've added the files to the index. – Christoffer Hammarström Jan 28 '10 at 15:50
  • `touch file; echo bla > file` gives `file: File exists` here; in that case it's safest to use `rm file; touch file; echo something >> file` (and probably many other solutions ;-)) – Kenney Dec 28 '13 at 15:55
  • 6
    If you just do `echo bla > file` you will not get `file: File exists` because `>` will overwrite the file if it's already there or create a new one if it doesn't exist. – psyrendust Apr 01 '14 at 19:53
  • 3
    `/bin/sh` cultural assumption!* If "here" is `csh` and the variable `noclobber` is set, you will indeed get `file: File exists`. If someone says "I get this", don't assume they're an idiot and reply "No you don't". * http://c2.com/cgi/wiki?AmericanCulturalAssumption – clacke Mar 16 '15 at 08:26
  • 1
    @clacke If someone decides to use a different shell than everyone else, they should state that expressly if they are encountering problems. Unlike with nationality, everyone has their free choice of shell. – Seldom 'Where's Monica' Needy May 25 '16 at 19:38
  • 2
    @SeldomNeedy Maybe they are looking for help because they don't even know they are using a different shell than everybody else. – clacke May 30 '16 at 08:37
19

Maybe adding an empty directory seems like it would be the path of least resistance because you have scripts that expect that directory to exist (maybe because it is a target for generated binaries). Another approach would be to modify your scripts to create the directory as needed.

mkdir --parents .generated/bin ## create a folder for storing generated binaries
mv myprogram1 myprogram2 .generated/bin ## populate the directory as needed

In this example, you might check in a (broken) symbolic link to the directory so that you can access it without the ".generated" prefix (but this is optional).

ln -sf .generated/bin bin
git add bin

When you want to clean up your source tree you can just:

rm -rf .generated ## this should be in a "clean" script or in a makefile

If you take the oft-suggested approach of checking in an almost-empty folder, you have the minor complexity of deleting the contents without also deleting the ".gitignore" file.

You can ignore all of your generated files by adding the following to your root .gitignore:

.generated
Brent Bradburn
  • 40,766
  • 12
  • 126
  • 136
  • 1
    Note: The symbolic link that I suggested is "broken" in a clean checkout because the `.generated` directory does not initially exist. It will no longer be broken once you do your build. – Brent Bradburn Mar 14 '12 at 00:14
  • 3
    I agree in some cases this is a very good idea, but in others (such as distributing a project where you have an otherwise empty skeleton with folders such as models/ and views/ ) you would want the user to have these directories at hand rather than manually having to read read the docs, and it could be a bit much to expect them to run some sort of installation script after cloning the repo. I think this answer in combination with @john-mee's README answer should cover most if not all cases. – moopet Jun 17 '14 at 08:28
14

I've been facing the issue with empty directories, too. The problem with using placeholder files is that you need to create them, and delete them, if they are not necessary anymore (because later on there were added sub-directories or files. With big source trees managing these placeholder files can be cumbersome and error prone.

This is why I decided to write an open source tool which can manage the creation/deletion of such placeholder files automatically. It is written for .NET platform and runs under Mono (.NET for Linux) and Windows.

Just have a look at: http://code.google.com/p/markemptydirs

14

You can't and unfortunately will never be able to. This is a decision made by Linus Torvald himself. He knows what's good for us.

There is a rant out there somewhere I read once.

I found Re: Empty directories.., but maybe there is another one.

You have to live with the workarounds...unfortunately.

GAMITG
  • 3,670
  • 7
  • 30
  • 50
user2334883
  • 371
  • 3
  • 4
  • 1
    I know you posted this as an example of a bad argument, but I appreciate the link because it's actually a well-reasoned argument against tracking directories. ;-) – clacke Mar 16 '15 at 08:32
  • 1
    This answer seems to be inconsistent, since in the next post on the referenced thread, Linus Torvald says he expects that they will need to add directory tracking: http://markmail.org/message/libip4vpvvxhyqbl . In fact, he says he "would welcome patches that [add support for tracking empty directories]" – Patrick M Aug 01 '17 at 20:12
  • Patrick, he also uses the word "idiotic" there. I suspect his wording adresses the people here in this thread and so I assume he will not implement something "idiotic" into Git by himself. – user2334883 Aug 03 '17 at 20:38
14

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.

Edit for a better solution

So, since most of our developers already have Ant installed, the first thing I thought of was to put together an Ant build file to accomplish this independently of the platform. This can still be found here

However, I later thought It would be better to make this into a small utility command, so I recreated it using Python and published it to the PyPI here. You can install it by simply running:

pip3 install gitkeep2

It will allow you to create and remove .gitkeep files recursively, and it will also allow you to add messages to them for your peers to understand why those directories are important. This last bit is bonus. I thought it would be nice if the .gitkeep files could be self-documenting.

$ 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.

I hope you find it useful.

Mig82
  • 3,665
  • 1
  • 30
  • 55
11

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.

GAMITG
  • 3,670
  • 7
  • 30
  • 50
Michael Johnson
  • 2,169
  • 15
  • 20
9

There's no way to get Git to track directories, so the only solution is to add a placeholder file within the directory that you want Git to track.

The file can be named and contain anything you want, but most people use an empty file named .gitkeep (although some people prefer the VCS-agnostic .keep).

The prefixed . marks it as a hidden file.

Another idea would be to add a README file explaining what the directory will be used for.

Zaz
  • 39,637
  • 10
  • 70
  • 92
9

As mentioned it's not possible to add empty directories, but here is a one liner that adds empty .gitignore files to all directories.

ruby -e 'require "fileutils" ; Dir.glob(["target_directory","target_directory/**"]).each { |f| FileUtils.touch(File.join(f, ".gitignore")) if File.directory?(f) }'

I have stuck this in a Rakefile for easy access.

GAMITG
  • 3,670
  • 7
  • 30
  • 50
Peter Hoeg
  • 863
  • 9
  • 12
  • 6
    I'd rather use `find . -type d -empty -print0 | xargs --null bash -c 'for a; do { echo "*"; echo "!.gitignore"; } >>"$a/.gitignore"; done' --` – Tino Oct 21 '11 at 06:35
9

Many have already answered this question. Just adding a PowerShell version here.

Find all the empty folders in the directory

Add a empty .gitkeep file in there

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}
Community
  • 1
  • 1
Hainan Zhao
  • 1,453
  • 14
  • 14
9

Reading @ofavre's and @stanislav-bashkyrtsev's answers using broken GIT submodule references to create the GIT directories, I'm surprised that nobody has suggested yet this simple amendment of the idea to make the whole thing sane and safe:

Rather than hacking a fake submodule into GIT, just add an empty real one.

Enter: https://gitlab.com/empty-repo/empty.git

A GIT repository with exactly one commit:

commit e84d7b81f0033399e325b8037ed2b801a5c994e0
Author: Nobody <none>
Date: Thu Jan 1 00:00:00 1970 +0000

No message, no committed files.

Usage

To add an empty directory to you GIT repo:

git submodule add https://gitlab.com/empty-repo/empty.git path/to/dir

To convert all existing empty directories to submodules:

find . -type d -empty -delete -exec git submodule add -f https://gitlab.com/empty-repo/empty.git \{\} \;

Git will store the latest commit hash when creating the submodule reference, so you don't have to worry about me (or GitLab) using this to inject malicious files. Unfortunately I have not found any way to force which commit ID is used during checkout, so you'll have to manually check that the reference commit ID is e84d7b81f0033399e325b8037ed2b801a5c994e0 using git submodule status after adding the repo.

Still not a native solution, but the best we probably can have without somebody getting their hands really, really dirty in the GIT codebase.

Appendix: Recreating this commit

You should be able to recreate this exact commit using (in an empty directory):

# Initialize new GIT repository
git init

# Set author data (don't set it as part of the `git commit` command or your default data will be stored as “commit author”)
git config --local user.name "Nobody"
git config --local user.email "none"

# Set both the commit and the author date to the start of the Unix epoch (this cannot be done using `git commit` directly)
export GIT_AUTHOR_DATE="Thu Jan 1 00:00:00 1970 +0000"
export GIT_COMMITTER_DATE="Thu Jan 1 00:00:00 1970 +0000"

# Add root commit
git commit --allow-empty --allow-empty-message --no-edit

Creating reproducible GIT commits is surprisingly hard…

ntninja
  • 760
  • 7
  • 15
8

The solution of Jamie Flournoy works great. Here is a bit enhanced version to keep the .htaccess :

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

With this solution you are able to commit a empty folder, for example /log, /tmp or /cache and the folder will stay empty.

Community
  • 1
  • 1
Roman
  • 2,061
  • 2
  • 22
  • 43
  • 2
    He wants to keep a empty directory and not a file. – gvsrepins Jul 29 '14 at 02:55
  • 2
    And i have mentioned that it will keep the .htaccess, too. Example: if a software has a directory for log-files (like oxid eshop) that should not be accesible via web, there is a .htaccess in the directory. If you put the above mentioned .gitignore in the folder, the .htaccess will not be comitted and the folder will be accessible via web. – Roman Jul 31 '14 at 08:17
  • If you have a .htaccess file that's under version control, then you already have the directory containing it under version control. Thus, the problem is already solved - the .gitignore file becomes irrelevant. – Ponkadoodle Jan 08 '17 at 09:11
  • 1
    @Wallacoloo Related to the question you're right, nevertheless the file is useful, I'll use it for an upload-directory like that where files shall be protected by .htaccess. Contrary to Romans explanation the .htaccess-file will be committed as it's excluded by the ignore-rule. [old thread, I know] – David Aug 28 '17 at 08:10
7

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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Stanislav Bashkyrtsev
  • 11,403
  • 7
  • 33
  • 38
7

I always build a function to check for my desired folder structure and build it for me within the project. This gets around this problem as the empty folders are held in Git by proxy.

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");
}

This is in PHP, but I am sure most languages support the same functionality, and because the creation of the folders is taken care of by the application, the folders will always be there.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Mild Fuzz
  • 26,058
  • 28
  • 95
  • 142
  • 3
    Just so we're all on the same page, I do not do this anymore. It's a waste of time. The `.gitkeep` convention is a much better practise. – Mild Fuzz Mar 25 '14 at 15:41
  • I can't see how this can be a waste of time. When your TEMPLATEPATH is obviously dynamic you can't use the .gitkeep solution. And even with a nondynamic folder structure you should add some more stuff instead of removing the very good solution of checking directories e.g. check for permissions and chmod the files. Adding a way to mark directories inside a global .gitignore would be perfect for me. Something like #keep /path/to/dir – Jochen Schultz Jun 02 '15 at 13:58
6

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! ;)

enter image description here

ajmedway
  • 1,404
  • 13
  • 26
6

An easy way to do this is by adding a .gitkeep file to the directory you wish to (currently) keep empty.

See this SOF answer for further info - which also explains why some people find the competing convention of adding a .gitignore file (as stated in many answers here) confusing.

arcseldon
  • 29,753
  • 14
  • 104
  • 117
6

This simple solution worked for me.

1. Add a .gitignore file to your empty directory:

*
*/
!.gitignore
  • * ignore all files in the folder
  • */ Ignore subdirectories
  • !.gitignore include the .gitignore file

2. Then remove your cache, stage your files, commit and push:

git rm -r --cached .
git add . // or git stage .
git commit -m ".gitignore fix"
git push
DevonDahon
  • 4,134
  • 2
  • 37
  • 57
5

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...)

Trendfischer
  • 5,591
  • 4
  • 33
  • 41
4

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.

Mike
  • 1,769
  • 15
  • 34
3

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.

Jörg W Mittag
  • 337,159
  • 71
  • 413
  • 614
  • 66
    I contest this view. **Structure** is content, and everything you **name** contributes to content. – ThomasH Aug 11 '11 at 12:08
  • 21
    An empty file isn't source code or content either. It's just a name. Yet Git will happily track empty files. I don't think it was an intentional design decision to make Git refuse to track empty directories. I think tracking empty directories is a feature that simply isn't needed 99% of the time, so they didn't bother to do the extra work required to make it work properly. Git can do it if someone wants the feature badly enough to implement it. I doubt the Git maintainers would be opposed to such a patch if it were done correctly. – Dan Moulding Sep 13 '11 at 15:32
  • 1
    @TobyAllen here is the updated [FAQ link](https://git.wiki.kernel.org/index.php/GitFaq#Can_I_add_empty_directories.3F) The top answer is also what is recommended by the FAQ with more precise instructions. – Daniel Da Cunha Apr 12 '13 at 07:22
  • 3
    It's a missing feature (and low priority), not an intentional limitation. From the Git FAQ: Currently the design of the Git index (staging area) only permits files to be listed, and **nobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it.** – jbo5112 Jun 04 '13 at 21:17
  • 1
    Don't really agree. I can find various reasons why I want to track an empty folder. For example, I am developing a very lightweight PHP MVC framework for my projects. I have specific folders for placing models, views, etc. When I make a new site based on my framework, those folders are empty since there are no models or views by default, but I do need the folder to exist, else my framework won't work! – Gladen Nov 25 '13 at 14:25
3

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

Then do

git commit -m "message"
git push
GAMITG
  • 3,670
  • 7
  • 30
  • 50
user665190
  • 47
  • 2
2

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.

Rahul Sinha
  • 1,021
  • 9
  • 15
2

To extend Jamie Flournoy's solution to a directory tree, you can put this .gitignore in the top-level directory and touch .keepdir in each subdirectory that git should track. All other files are ignored. This is useful to ensure a consistent structure for build directories.

# Ignore files but not directories. * matches both files and directories
# but */ matches only directories. Both match at every directory level
# at or below this one.
*
!*/

# Git doesn't track empty directories, so track .keepdir files, which also 
# tracks the containing directory. 
!.keepdir

# Keep this file and the explanation of how this works
!.gitignore
!Readme.md
aball
  • 46
  • 3
2

Just add empty (with no content) .gitignore file in the empty directory you want to track.

E.g. if you want to track empty dir /project/content/posts then create new empty file /project/content/posts/.gitignore

Note: .gitkeep is not part of official git:

enter image description here

Sohel Ahmed Mesaniya
  • 3,013
  • 1
  • 19
  • 29
1

I search into this question becuase: I create a new directory and it contains many files. Among these files, some I want to add to git repository and some not. But when I do "git status". It only shows:

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    ../trine/device_android/

It does not list the seperate files in this new directory. Then I think maybe I can add this directory only and then deal with the seperate files. So I google "git add directory only".

In my situation, I found I can just add one file in the new directory that I am sure I want to add it to git.

git add new_folder/some_file

After this, "git status" will show the status of seperate files.

Yi Zhao
  • 194
  • 1
  • 11
-6

Just add a readme or a .gitignore and then delete it, not from terminal, from the github website, that will give a empty repository

Aroo
  • 37
  • 8
  • 6
    They were asking for an empty directory, not an empty repository. Also, you’ve assumed they are using GitHub when they only talked about git. – Brook Jordan Sep 10 '20 at 03:57