105

I've recently started using Git and am having trouble with just one thing. How can I track directories without tracking their contents?

For example the site I'm working on allows uploads. I want to track the uploads directory so that it is created when branching, etc. but obviously not the files within it (test files whilst in develop branch or the real files in master).

In my .gitignore I have the following:

uploads/*.*

Have also tried (which ignores the whole directory):

uploads/

This directory may also contain sub directories (uploads/thumbs/ uploads/videos/) I would like to be able to track these but not their files.

Is this possible with Git? I've searched everywhere without finding an answer.

Ben
  • 1,435
  • 3
  • 10
  • 10
  • Git only tracks files. What you could do is play around with git hooks and track a file that will contain the directory listing (auto-generated using the hooks). Although I'm not entirely sure if that would be possible. – Šimon Tóth Feb 23 '11 at 12:49
  • More concrete: Git tracks _content_ and (for git) an empty directory is not content. You can argue, wether you agree, or not, but as another "workaround" you may think about creating the directories on build/install/when-needed. However: I use the "`.placeholder`-file"-solution also ;) – KingCrunch Feb 23 '11 at 13:00
  • 1
    Rather than use .placeholder, I use a .gitignore file. Not only does this take care of the exclusions within the directory, but it acts as a placeholder itself. – Abizern Feb 23 '11 at 13:04

6 Answers6

133

Git doesn't track directories, it tracks files, so to acheive this you need to track at least one file. So assuming your .gitignore file looks something like this:

upload/*

You can do this:

$ touch upload/.placeholder
$ git add -f upload/.placeholder

If you forget the -f you'll see:

$ git add upload/.placeholder
The following paths are ignored by one of your .gitignore files:
upload
Use -f if you really want to add them.
fatal: no files added

Then when you do git status you'll see:

# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached ..." to unstage)
#
#   new file:   upload/.placeholder
#

Obviously you can then do:

$ touch upload/images/.placeholder
$ git add -f upload/images/.placeholder
Peter Farmer
  • 9,020
  • 5
  • 27
  • 29
50

Best answerd I've found is to include a .gitignore file in your upload folder with this content

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

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

Community
  • 1
  • 1
Gonzalo Cao
  • 2,286
  • 1
  • 24
  • 20
40

I wrote about this here.

Add a .gitignore within the directory.

Abizern
  • 146,289
  • 39
  • 203
  • 257
18

The best solution so far:

1) Create a .gitignore file

2) Write inside:

*
*/
!.gitignore

3) Add the .gitignore file to the folder that you want.

Source: https://stackoverflow.com/a/5581995/2958543

Community
  • 1
  • 1
mejiamanuel57
  • 6,807
  • 1
  • 32
  • 34
10

In order to track only directories but not the files, I did the following. Thanks to the @PeterFarmer's comment on git tracking only files, I've been able to keep all directories excluding the files as described in below.

# exclude everything in every folder
/data/**/*.*

# include only .gitkeep files
!/data/**/*.gitkeep

Adding this to the .gitignore file will do the work. The following is my folder structure.

data/
├── processed
│   ├── dataset1.csv
│   └── dataset2.csv
├── raw
│   ├── raw_dataset1.json
└── test
    ├── subfolder
    │   └── dataset2.csv
    └── reviews.csv

When I do git add . && git status, git only recognizes folders, but not files.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   .gitignore
        new file:   data/processed/.gitkeep
        new file:   data/raw/.gitkeep
        new file:   data/test/.gitkeep
        new file:   data/test/subfolder/.gitkeep

Keep in mind that the following for your .gitignore files:

Prepending slash looks only for the root directory.

/dir

Double asterisk looks for zero or more directories.

/**/

metinsenturk
  • 421
  • 7
  • 9
3

(In your example, directory is uploads.)

In the root directory, in a .gitignore file, put:

directory/*
!*.gitkeep

Then save an empty .gitkeep file in directory.

Denziloe
  • 7,473
  • 3
  • 24
  • 34