.gitignore 如何排除整个文件夹但保留某个子文件夹
.gitignore 排除文件夹但保留子文件夹的写法:先 main/ 排除全部,再 !main/subfolder/ 取反保留。注意不能写 main/(整目录排除后无法取反),必须用星号配合感叹号逐层取反。
用"先排除、再取反"的规则对:写 main/* 排除文件夹下所有内容,再写 !main/subfolder/ 把要保留的子文件夹捞回来。关键陷阱:不能写 main/ 整体排除——目录被整体排除后 Git 不会进入它,里面的取反规则永远不会生效。
正确写法
目录结构:
project/
├── main/
│ ├── subfolder1/
│ ├── subfolder2/ ← 只想保留它
│ └── subfolder3/
└── .gitignore
# 排除 main 下的所有内容
main/*
# 但保留 subfolder2
!main/subfolder2/
更深层级的保留
要保留 main/a/b/ 这种嵌套目录,需要逐层取反:
main/*
!main/a/
main/a/*
!main/a/b/
每一层都是"排除同级 → 放行目标"的组合。
验证规则是否生效
git check-ignore -v main/subfolder2/file.txt # 无输出 = 未被忽略
git check-ignore -v main/subfolder1/file.txt # 输出匹配的规则行
git status --ignored # 总览被忽略的文件
常见问题(FAQ)
Q:为什么 ! 取反没生效?
三个常见原因:① 父目录是被 dir/ 整体排除的(改用 dir/*);② 取反行写在了排除行之前(后面的规则优先级高,顺序要对);③ 子文件夹里没有任何可被跟踪的文件——Git 不跟踪空目录,需要放一个 .gitkeep。
Q:已被跟踪的文件加进 gitignore 还有效吗?
无效。gitignore 只管"未跟踪"文件。已跟踪的要先 git rm --cached <文件> 移出索引再提交。
Q:能排除所有 .log 但保留 important.log 吗?
可以,同样模式:*.log 加 !important.log。