If this is all my fault, I'm sorry.
https://github.com/rails/rails/commit/785493ffed41abcca0686b...
Some devs will just open the first gitignore they see and throw stuff into it. No thank you.
This is not a complicated or important enough problem to justify a team-wide policy. Let it work itself out naturally.
https://git-scm.com/docs/git-check-ignore makes it trivial to debug repo-wide gitignore behavior.
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.
Additionally, the AI comment is ironic as well. It's like we're finally writing good documentation for the sake of agents, in a way that we should have been writing all along for other sentient consumers. It's funny to see documentation now as basically the horse instead of the cart.
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. $ echo '*\n!.gitignore' > build/.gitignore
The \n won't be interpreted specially by echo unless it gets the -e option.Personally if I need a build directory I just have it mkdir itself in my Makefile and rm -rf it in `make clean`. With the article's scheme this would cause `git status` noise that a `/build/` line in a root .gitignore wouldn't. I'm not really sure there's a good tradeoff there.
Author's probably using Zsh, which interprets them by default.
What an arrogant take. This is preference. Don’t mistake it for correctness.
It's not that hard to update a .gitignore file every now and then.
Using the actual tools built in to git directly removes steps in the process, which is always a good thing, it's documented as part of the git documentation, so you don't have to create a wiki page explaining why there is a ".gitkeep" file that git doesn't recognize itself.
Saying "It's not that hard..." is fine for projects with a few contributors but does not scale.
Your point is valid though. It would be much preferable to include build/ in your root .gitignore so that the directory is never tracked.
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. :(
You will have proper diff for the tree this way.
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 rely on `add -f` you will forget to commit something important.
For example, for a tree sitter grammar I developed a couple years ago, here is my .gitignore:
```
# Ignore everything
*
# Top-level whitelist
CHANGELOG.md
# Allow git to see inside subdirectories
!*/
# Whitelist the grammar and tests
!/grammar/*.js
!/test/corpus/*.txt
# Whitelist any grammar and tests in subdirectories
!/grammar/**/*.js
!/test/corpus/**/*.txt
```*
But isn't the idea in TFA to blacklist the entire `build/` tree? We don't want to add anything there.
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.
That is what I have always used them for....
Better yet just do the work. If you want make a commit in a branch that's destined to be squashed or something, sure, but keep it away from the shared history and certainly remove it when it's not needed anymore.
To manually install it, you must clone the repo. Then you have to download models into the right place. Where's the right place? Well, there's an empty directory called models. They go in there.
IMO that's an effective use of gitkeep.
echo >repo/models/README.md "this is the directory you place models in"
Is infinitely better.https://github.com/Comfy-Org/ComfyUI/blob/master/models/diff...
But in any case, that instruction was already in the readme as well.
The simplest answer is that sometimes other existing software that I need to use treats an empty directory (or, hopefully, a directory containing just an irrelevant file like .gitkeep) differently from an absent directory, and I want that software to behave in the first way instead of the second.
A more thorough answer would be: Filesystems can represent empty directories, so a technology that supports versioned filesystems should be able to as well. And if that technology can't quite support fully versioned filesystems -- perhaps because it was never designed with that goal in mind -- but can nevertheless support them well enough to cover a huge number of use cases that people actually have, then massaging it a bit to handle those rough edges still makes sense.
Many filesystems cannot represent empty directories. Many archive formats also do not. I don't think this a problem in practice. I find this argument extremely weak.
Like which ones? And how does mkdir(1) work on such filesystems?
touch build/.gitkeep
git add build/.gitkeep
git commit build/.gitkeep
And that's it? There's no need to exclude anything.".gitkeep" is just a human thing; it would work the same if you called it ".blahblah".
So their pitch is that if you want to explicitly keep the existence of the directory as a committed part of the repo, you're better off using the actual .gitignore functionality to check in the .gitignore file but ignore anything else in the directory.
I don't find it amazingly compelling; .gitkeep isn't breaking anything.
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.