Git默认不保留空目录,因其只跟踪文件而非目录;解决方法是在空目录中添加.gitkeep空文件并提交,该文件名是社区约定,无特殊逻辑但语义明确。

为什么 Git 默认不保留空目录
Git 只跟踪文件,不跟踪目录本身。只要一个目录下没有任何被 Git 认为“可追踪”的文件(即未被 .gitignore 排除、且未被 git rm --cached 移除的文件),这个目录在 clone 或 checkout 时就会直接消失。这不是 bug,是设计使然。
常见错误现象包括:git status 不显示空目录、远程仓库里结构“少了一层”、CI 构建时报 No such file or directory 路径不存在。
用 .gitkeep 是最直接的约定做法
在空目录里放一个空文件,名字叫 .gitkeep,然后 git add 它——Git 就会把该目录连同这个文件一起纳入索引。这个文件名没有特殊逻辑,只是社区长期形成的共识,别人一看就懂意图。
实操建议:
- 手动创建:进入目标空目录,执行
touch .gitkeep(Linux/macOS)或type nul > .gitkeep(Windows CMD) - 确保它没被
.gitignore拦截:检查根目录.gitignore是否有类似*.keep或.git*的泛匹配行;如有,加一行!.gitkeep显式放行 - 不需要写内容,0 字节即可;也不需要
chmod或其他元数据操作
批量处理多个空目录时慎用 find -empty
命令 find . -type d -empty -exec touch {}/.gitkeep \; 看似省事,但容易踩坑:
- 它会递归扫描所有子目录,包括
.git、node_modules等本不该碰的路径——建议限定范围,比如find ./src -type d -empty -exec touch {}/.gitkeep \; -
-empty判断的是“无文件且无子目录”,但若目录下已有隐藏文件(如.DS_Store),它就不算 empty,命令会跳过 - 执行前先用
find . -type d -empty预览一遍,确认结果符合预期
.gitignore 方案看似灵活,实际更易出错
有人尝试在空目录里放 .gitignore,内容写成:
# Ignore everything in this directory * # Except this file !.gitignore
这确实能让 Git 跟踪该目录,但问题在于:
- 这个
.gitignore文件本身会生效——后续往该目录加任何新文件(比如config.json),都会被自动忽略,除非手动改.gitignore - 如果目录层级深,或者要保留的只是“结构占位”,而不是“未来也需忽略内容”,那这种方案反而增加维护负担
- 和
.gitkeep相比,它多了一层语义混淆:到底是“这里永远为空”,还是“这里以后只允许特定文件”?
真正需要保留空目录的场景,几乎都只需要一个明确的信号文件,.gitkeep 就是那个信号——轻量、无副作用、可预测。


















