Don't create .gitkeep files, use .gitignore instead
Source: Hacker News
2023-09-18
Git only tracks files, not directories. It will only create a directory if it contains a tracked file. But sometimes you need to “track” a directory, to ensure it exists for fresh clones of a repository. For example, you might need an output directory called build.
In this post, we’ll look at two ways to achieve this. First, the common but slightly flawed .gitkeep technique, then a simpler one using only a .gitignore file.
The .gitkeep technique
This technique uses an empty file called .gitkeep:
build
└── .gitkeepThe empty file ensures that Git creates the directory with minimal cost. Any other filename may be used, as Git doesn’t treat .gitkeep files any differently.
To set this up, you might create an empty file with touch:
$ touch build/.gitkeepThen ignore all files in the directory, except .gitkeep, by adding patterns in the repository’s .gitignore file:
/build/*
!/build/.gitkeepThe first pattern ignores everything in the build directory. The second one then un‑ignores the .gitkeep file, allowing it to be committed.
Downsides
- It requires editing two files.
- If the directory is renamed,
.gitignoreneeds updating, which is easy to miss. .gitkeepis not a name recognized by Git, so there’s no documentation on it, potentially confusing other developers.
The better .gitignore technique
This technique uses only a short .gitignore file inside the directory:
build
└── .gitignoreThe .gitignore file has these contents:
*
!.gitignoreThe first pattern ignores all files in the directory. The second one then un‑ignores the .gitignore file, so it can be committed.
You can create this file with echo and file redirection:
$ echo '*\n!.gitignore' > build/.gitignoreWhen you add and commit the directory, Git will pick up the .gitignore file first, skipping other files within the directory:
$ git add build
$ git status
On branch main
Changes to be committed:
new file: build/.gitignore
$ git commit -m "Track build directory"
[main 1cc9120] Track build directory
1 file changed, 2 insertions(+)
create mode 100644 build/.gitignoreThe directory is now “tracked” with a single, standard file that will work even after renames.
Conclusion
Don’t ignore this technique.