When you tell it to ignore *
, Git will not recurse into any subdirectories (even though you have a “unignore” pattern that might match something inside one of the directories).
There is a bit of the gitignore pattern language that might help though. A trailing slash forces the pattern to only apply to directories. So, you should be able to use this:
# .gitignore
*
!.keep
!*/
In the demonstration below I use the above .gitignore
and have an additional file (named do-not-keep
) alongside each .keep
file. You can see that it works for multiple levels of subdirectories and does not show the other files. You will have to arrange for each directory to have its own .keep
(or whatever) via some independent method.
% git status --short -uall
?? a/.keep
?? a/b/.keep
?? a/b/c/.keep
?? a/b/c/d/.keep
?? e/.keep
?? e/f/.keep
?? e/f/g/.keep
?? h/.keep
?? h/i/.keep
?? j/.keep
This was done with Git 1.7.3.1, but I expect that it will work for other versions as well.
The demonstration setup:
% git init
% mkdir -p a/b/c/d e/f/g h/i j
% zargs -i.. -- **/*(/) -- touch ../.keep ../do-not-keep
% tree -aI .git .
.
|-- .gitignore
|-- a
| |-- .keep
| |-- b
| | |-- .keep
| | |-- c
| | | |-- .keep
| | | |-- d
| | | | |-- .keep
| | | | `-- do-not-keep
| | | `-- do-not-keep
| | `-- do-not-keep
| `-- do-not-keep
|-- e
| |-- .keep
| |-- do-not-keep
| `-- f
| |-- .keep
| |-- do-not-keep
| `-- g
| |-- .keep
| `-- do-not-keep
|-- h
| |-- .keep
| |-- do-not-keep
| `-- i
| |-- .keep
| `-- do-not-keep
`-- j
|-- .keep
`-- do-not-keep
10 directories, 21 files