I'm using Git for version control and have been battling with the system/expressionengine/cache folder a bit. Someone had removed it from the repo using an ignore, but then we got php errors because the latest version file could not be found. Add ons like Channel Images use this folder to cache some files. I've been putting git ignore files in these folders:

# Ignore everything in this directory
# Except this file

This leaves the folder in the repo, but keeps it empty. Seems to work, but wonder if there is a better way.

5 Answers 5


Since Git can currently only stage files and not empty directories, the only purely Git based solution is to do as you are now.

An alternative approach is to include a bash script in your repo that creates any required cache directories if the do not exist and (importantly) sets permissions on these directories (which often needs to be 755/777).

The advantage of this approach comes when you need to deploy to a new server/get a new dev up and running on an install - you no longer have to manually check permissions etc - just run the script and everything will be in it's right place. I use DeployHQ's post-deploy script functionality to do this when deploying EE.


The other answers are going about this a slightly convoluted way. You don't need a special .gitignore in each folder, and that makes it hard for other developers to figure out what's going on (or you in a few months).

Just ignore the whole cache folder in your root .gitignore:

$ cd /path/to/root
$ echo "system/expressionengine/cache/" >> .gitignore

Then, the standard git practice for empty directories is to add an empty file named .gitkeep:

$ touch system/expressionengine/cache/.gitkeep

Since EE ships with an index.html file in the cache directory, you can use that instead. As long as the directory has at least one file in it, it will get created on your live server.

You also don't need to add any extra gitignore rules to exclude this file. Just add that particular file using --force (which overrides any gitignore instructions):

$ git add --force system/expressionengine/cache/index.html
$ git commit -m "Add index.html file to cache directory"

Now your folder will always get created, but git won't ever bother telling you about changes to that directory. You should do the same thing for all the images/ directories as well.

  • 1
    I wasn't aware of the .gitkeep practice and have been in the habit of creating empty .gitignore files instead. It's functionally identical but this SO answer makes the case that .gitkeep is the more semantic approach, which is a valid point.
    – Dom Stubbs
    Nov 29, 2012 at 14:24

A possibly cleaner way would be to have it in your .gitignore at the root level of your repo...


... that way everything's centralized in that one .gitignore. However it's my preferred method to have multiple .gitignore files (like your example above), one in each "empty" directory that I want to have tracked in the repo.

I'd say it boils down to personal preference.

Updated / Extended Answer:

It's been pointed out by @DomStubbs below that it would be cleaner to globally track all .gitignore files with:


If you do that, then you can remove:


Globally tracking all .gitignore files also means that the .gitignore in each "empty" directory should be a blank file, as it effectively turns into a placeholder like the .gitkeep file that @AdrianMacneil mentions in his answer.

So that all said, here's an example of what the "Ignore Cache Files" section of your root-level .gitignore could look like if you used the "empty placeholder .gitkeep/.gitignore" method:

# Track all .gitignore files
!.gitignore # or !.gitkeep if you prefer

# Ignore all cache files

But that's only if you want to 1) explicitly define all "empty" directories that you want to track in the root .gitignore and 2) put a blank placeholder .gitkeep/.gitignore in every "empty" directory.

I think that it's much easier to manage which "empty" directories to track by using the .gitignore that @Doug refers to in the original question. Want to declare a directory as "empty" and ignore its contents? Throw in the .gitignore file. Want to start tracking the contents? Delete the .gitignore file. Want to stop tracking the directory entirely? Delete the .gitignore file and exclude the directory in the root .gitignore file. This is more efficient because there is only ever one point of reference for the tracking state of these "empty" directories.

I have now spent far too much time thinking about this topic. :-) However, I am now much more pleased with the "exclude-everything-but-me .gitignore" method. Thanks, everyone!

  • 2
    I'd suggest changing !system/expressionengine/cache/.gitignore to !.gitignore. This eliminates the need to create negating patterns for each individual 'empty' directory.
    – Dom Stubbs
    Nov 29, 2012 at 12:51
  • @DomStubbs - you make a good point. Reviewing my answer also makes me realize that--even though I'm positioning this as a cleaner method for tracking empty directories--my solution would necessarily be more complex, as it requires a .gitignore at the root level of the repo as well as one in each "empty" directory. Nov 29, 2012 at 14:16

We use a single .gitignore file in the root directory, and we specifically list all subfolders. This way, the cache folder can contain the default index.html file, and will be indexed by git.


We set permissions on the main cache folder, and EE is able to create cache folders on its own. This has worked well for us!


You probably got errors because EE couldn't find the cache folder. I'm new to git, and I have all my ignore rules in one file in the root and there I have this

# Cache
  • Mine are very similar to yours Davor. Nov 28, 2012 at 23:27
  • 1
    Forgot to mention that my system folder is renamed and this is solution for system folder above the root
    – Davor Peic
    Nov 28, 2012 at 23:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.