I'm not sure if I'm the one to blame for this or not, but the earliest reference to ".gitkeep" I can find online is my 2010 answer on Stack Overflow: https://stackoverflow.com/a/4250082/28422
If this is all my fault, I'm sorry.
show comments
Arrowmaster
The author makes a very common mistake of not reading the very first line of the documentation for .gitignore.
A gitignore file specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected; see the NOTES below for details.
You should never be putting "!.gitignore" in .gitignore. Just do `echo "*" > .gitignore; git add -f .gitignore`. Once a file is tracked any changes to it will be tracked without needing to use --force with git add.
show comments
hollasch
My preference is to use the build system to create built artifacts, and I consider the build/ directory to be a built artifact. Wrangling Git into doing the first fundamental build step is off, in my opinion.
However, if you disagree, my favorite "Git keep" filename is "README.md". Why is this otherwise empty directory here, how does it fit into my source tree, how is it populated, and so forth.
One of my pet peeves with the latest AI wave is the time we spend creating files to help AI coding agents, but don't give the same consideration to the humans who have to maintain and update our code.
show comments
Joker_vD
Why did Git decide to have no means to track fully empty directories? Like, I understand that e.g. doing "git rm *" inside a directory should probably delete this directory from the repository as well (although "git rm -r dir_to_delete" exists so...) but why not have a command to explicitly force a directory to be tracked, whether it's empty or not?
GreenDolphinSys
.gitkeep is intuitive and easy to understand. Unignoring a .gitignore is not intuitive. This falls squarely into "clever optimization tricks that obscure intent and readability". Don't do things like this.
It's not that hard to update a .gitignore file every now and then.
show comments
cortesoft
Not sure why you can’t just have your build script create the build directory?
show comments
zahlman
Oh, man, I'd forgotten about these negated .gitignore patterns entirely. It actually hadn't occurred to me that they could override the behaviour of ignoring empty directories.
This is potentially actually useful for me, because I have a project with test data that consists of miniature filesystem sub-trees — that should include empty directories to ensure edge cases are covered. I've been zipping them up and having the test harness unpack them in the test environment, but that's an unnecessary extra point of failure (and it stuffs undiffable binary files into the commit history).
Edit: Ah, no, if this doesn't work from the project-global .gitignore (specifying a folder to keep, even though it's empty and doesn't even have its own .gitignore) then it doesn't solve the problem. :(
show comments
prmoustache
How about fixing your build scripts and makefiles instead? Convoluted solutions for a non-existing problem.
beej71
What am I missing about this use case? It seems like you should just create `build/.gitignore` with `*` in it and `add -f` it and be done.
I'd use `.gitkeep` (or an empty `.gitignore`) if I needed to commit an otherwise-empty hierarchy. But if I'm going to have a `.gitignore` in there anyway, it's not empty.
> The directory is now “tracked” with a single, standard file that will work even after renames.
Does `.gitkeep` not work after renames? Or `.gitignore`?
So I am missing something. :)
show comments
Kuraj
If you need to do this, I think .gitkeep communicates intent better. You don't need to document it or risk it being removed as thought to be a left over.
8cvor6j844qw_d6
Is .gitkeep an established convention somewhere? I'm curious where the name originated.
show comments
jiffygist
I don't understand why would you ever want to have an empty directory. Besides if I see a directory named "build" I expect to be able to just nuke it any time without consequences.
OptionOfT
For me, I put them in directories that have to be there, because the underlying code doesn't create the directory, and without it, it fails.
Another example is where you want an empty directory mounted in Docker. If the directory is not there it is created with root permissions and then I can't even look into it.
kderbyma
Arent Gitkeep files specifically for empty folders that are intended to be there?
That is what I have always used them for....
globular-toast
I find this use of .gitignore far more common than .gitkeep. I did see one js tool creating them and did wonder what it was about.
suralind
I want to like it, but I pretty much always have a "cleanup" script that just deletes the entire directory and touches a .gitkeep file. Obviously an even better pattern is to not have any .gitkeep files, but sometimes they are just handy.
dmarinus
if possible you can also just create directories if they don't exist (ie. mkdir -p) and just exclude it in your root .gitignore (ie. ignore all build directories). That would safe you from creating multiple .gitignore files.
macote
The author is misusing .gitkeep. I use it to keep source code folders that don’t contain any code yet, but whose structure is already defined.
show comments
yjftsjthsd-h
I'm confused. Having a file gitignored doesn't stop you from committing it; AFAIK you can just
And that's it? There's no need to exclude anything.
show comments
leecommamichael
This doesn’t solve a problem.
cyberrock
File filtering is so delightfully broken everywhere. Everytime I revisit git, rsync, restic, borg, etc. something just goes wrong somewhere on this seemingly simple task, and SO and thus LLMs are filled to the brim with slightly wrong answers. We need a xkcd/927 because it can't possibly get any worse.
deafpolygon
Claims the wrong thing is common and tells you not to do it , then tells you to do the right thing.
I have never heard of .gitkeep before today, and if you need an empty directory to exist, use a build script.
I'm not sure if I'm the one to blame for this or not, but the earliest reference to ".gitkeep" I can find online is my 2010 answer on Stack Overflow: https://stackoverflow.com/a/4250082/28422
If this is all my fault, I'm sorry.
The author makes a very common mistake of not reading the very first line of the documentation for .gitignore.
You should never be putting "!.gitignore" in .gitignore. Just do `echo "*" > .gitignore; git add -f .gitignore`. Once a file is tracked any changes to it will be tracked without needing to use --force with git add.My preference is to use the build system to create built artifacts, and I consider the build/ directory to be a built artifact. Wrangling Git into doing the first fundamental build step is off, in my opinion.
However, if you disagree, my favorite "Git keep" filename is "README.md". Why is this otherwise empty directory here, how does it fit into my source tree, how is it populated, and so forth.
One of my pet peeves with the latest AI wave is the time we spend creating files to help AI coding agents, but don't give the same consideration to the humans who have to maintain and update our code.
Why did Git decide to have no means to track fully empty directories? Like, I understand that e.g. doing "git rm *" inside a directory should probably delete this directory from the repository as well (although "git rm -r dir_to_delete" exists so...) but why not have a command to explicitly force a directory to be tracked, whether it's empty or not?
.gitkeep is intuitive and easy to understand. Unignoring a .gitignore is not intuitive. This falls squarely into "clever optimization tricks that obscure intent and readability". Don't do things like this.
It's not that hard to update a .gitignore file every now and then.
Not sure why you can’t just have your build script create the build directory?
Oh, man, I'd forgotten about these negated .gitignore patterns entirely. It actually hadn't occurred to me that they could override the behaviour of ignoring empty directories.
This is potentially actually useful for me, because I have a project with test data that consists of miniature filesystem sub-trees — that should include empty directories to ensure edge cases are covered. I've been zipping them up and having the test harness unpack them in the test environment, but that's an unnecessary extra point of failure (and it stuffs undiffable binary files into the commit history).
Edit: Ah, no, if this doesn't work from the project-global .gitignore (specifying a folder to keep, even though it's empty and doesn't even have its own .gitignore) then it doesn't solve the problem. :(
How about fixing your build scripts and makefiles instead? Convoluted solutions for a non-existing problem.
What am I missing about this use case? It seems like you should just create `build/.gitignore` with `*` in it and `add -f` it and be done.
I'd use `.gitkeep` (or an empty `.gitignore`) if I needed to commit an otherwise-empty hierarchy. But if I'm going to have a `.gitignore` in there anyway, it's not empty.
> The directory is now “tracked” with a single, standard file that will work even after renames.
Does `.gitkeep` not work after renames? Or `.gitignore`?
So I am missing something. :)
If you need to do this, I think .gitkeep communicates intent better. You don't need to document it or risk it being removed as thought to be a left over.
Is .gitkeep an established convention somewhere? I'm curious where the name originated.
I don't understand why would you ever want to have an empty directory. Besides if I see a directory named "build" I expect to be able to just nuke it any time without consequences.
For me, I put them in directories that have to be there, because the underlying code doesn't create the directory, and without it, it fails.
Another example is where you want an empty directory mounted in Docker. If the directory is not there it is created with root permissions and then I can't even look into it.
Arent Gitkeep files specifically for empty folders that are intended to be there?
That is what I have always used them for....
I find this use of .gitignore far more common than .gitkeep. I did see one js tool creating them and did wonder what it was about.
I want to like it, but I pretty much always have a "cleanup" script that just deletes the entire directory and touches a .gitkeep file. Obviously an even better pattern is to not have any .gitkeep files, but sometimes they are just handy.
if possible you can also just create directories if they don't exist (ie. mkdir -p) and just exclude it in your root .gitignore (ie. ignore all build directories). That would safe you from creating multiple .gitignore files.
The author is misusing .gitkeep. I use it to keep source code folders that don’t contain any code yet, but whose structure is already defined.
I'm confused. Having a file gitignored doesn't stop you from committing it; AFAIK you can just
And that's it? There's no need to exclude anything.This doesn’t solve a problem.
File filtering is so delightfully broken everywhere. Everytime I revisit git, rsync, restic, borg, etc. something just goes wrong somewhere on this seemingly simple task, and SO and thus LLMs are filled to the brim with slightly wrong answers. We need a xkcd/927 because it can't possibly get any worse.
Claims the wrong thing is common and tells you not to do it , then tells you to do the right thing.
I have never heard of .gitkeep before today, and if you need an empty directory to exist, use a build script.
Don’t do stupid workarounds.
No, thanks