很多人第一次用 Git 时,都会遇到一个很尴尬的问题:明明已经写了 .gitignore,为什么文件还是被提交上去了?
比如:
node_modules/
.env
dist/
看起来没毛病,对吧?
可现实往往是:node_modules 还在 Git 里,.env 也已经被提交过,甚至团队成员一拉代码,发现你的本地配置、日志文件、构建产物全都混进了仓库。
.gitignore 是 Git 里非常基础的文件,但它背后的规则并不总是直觉化。今天这篇文章,我们就用最接地气的方式,把 .gitignore 的写法、常见坑和最佳实践一次讲清楚。
命令速查表
| 命令 | 中文注释 |
|---|---|
git status |
查看当前有哪些文件被修改、未跟踪,方便确认 .gitignore 是否生效 |
git check-ignore -v 文件路径 |
查看某个文件为什么被忽略,并显示命中的具体规则 |
git rm --cached 文件路径 |
取消 Git 对某个已跟踪文件的管理,但保留本地文件 |
git rm -r --cached 目录/ |
取消 Git 对某个已跟踪目录的管理,但保留本地内容 |
git add .gitignore |
把 .gitignore 文件加入暂存区,准备提交 |
git commit -m "说明" |
提交本次忽略规则或文件跟踪状态的变更 |
git config --global core.excludesfile ~/.gitignore_global |
设置全局忽略文件,适合放个人环境规则 |
git clean -fd |
删除未跟踪文件和目录,慎用,执行前先确认清单 |
.gitignore 是干什么的?
简单说,.gitignore 用来告诉 Git:
哪些文件或目录不需要被 Git 跟踪。
比如项目里经常会有这些内容:
- 依赖目录:
node_modules/ - 编译产物:
dist/、build/ - 本地配置:
.env - 日志文件:
*.log - 编辑器配置:
.vscode/、.idea/ - 系统文件:
.DS_Store
这些文件通常不应该进入代码仓库。
原因也很简单:
- 它们可能很大,比如依赖目录。
- 它们可能每个人都不一样,比如本地配置。
- 它们可能包含敏感信息,比如数据库密码、API Key。
- 它们可能是自动生成的,不需要人工维护。
所以,.gitignore 的核心价值不是“让仓库看起来干净”,而是让团队协作更稳定、更安全。
基础写法:先看懂这几种规则
.gitignore 的语法不复杂,但有几个细节很容易混。
忽略单个文件
.env
这表示忽略名为 .env 的文件。
它不仅会忽略项目根目录下的 .env,也可能匹配子目录里的同名文件。
如果你只想忽略根目录下的 .env,可以写:
/.env
开头的 / 表示从 .gitignore 所在目录开始匹配。
忽略某类文件
*.log
这表示忽略所有 .log 结尾的文件,比如:
app.log
error.log
debug.log
这类规则常用于日志、临时文件、缓存文件。
忽略整个目录
node_modules/
dist/
build/
结尾的 / 表示目录。
虽然有时候不写 / 也能生效,但建议目录一定加上 /,可读性更好,也更不容易误伤同名文件。
取消忽略某个文件
有时候我们想忽略一类文件,但保留其中某一个。
比如忽略所有 .env 文件,但保留 .env.example:
.env
.env.*
!.env.example
这里的 ! 表示“不要忽略”。
这在团队项目里很常见。真正的 .env 不提交,但提供一个 .env.example,告诉别人需要配置哪些环境变量。
DATABASE_URL=
REDIS_HOST=
API_KEY=
这样既安全,又方便新人启动项目。
最容易踩的坑:文件已经被 Git 跟踪了
这是 .gitignore 里最经典的坑。
你写了:
.env
但 .env 还是出现在 git status 里。
为什么?
因为 .gitignore 只对“尚未被 Git 跟踪”的文件生效。
如果某个文件之前已经被提交过,Git 已经认识它了,那么后来再把它加进 .gitignore,Git 仍然会继续跟踪它。
解决方式是:
git rm --cached .env
这个命令的意思是:
从 Git 跟踪列表里移除
.env,但保留本地文件。
然后再提交一次:
git commit -m "chore: stop tracking env file"
如果是整个目录,比如 node_modules/,可以用:
git rm -r --cached node_modules/
这一步非常重要。很多人以为 .gitignore 没生效,其实是文件早就被 Git 盯上了。
坑二:把 .env 提交过,风险已经发生了
如果你曾经把 .env 提交到远程仓库,即使后来删除了,也要小心。
因为 Git 历史里可能仍然能找到它。
这意味着:如果里面有数据库密码、Token、密钥,最好立刻更换。
不要只是提交一个“删除 .env”的 commit 就觉得安全了。
更稳妥的做法是:
- 立刻更换泄露的密钥。
- 从当前仓库移除
.env。 - 把
.env加入.gitignore。 - 提供
.env.example。 - 如果仓库公开过,考虑清理 Git 历史。
这里可以记一句话:
密钥一旦进过 Git,就应该视为已经泄露。
这不是危言耸听,而是工程实践里的基本安全意识。
坑三:忽略规则写得太宽,误伤重要文件
比如你写了:
config/
看起来是想忽略本地配置目录。
但如果项目里真正的业务配置也放在 config/ 里,那就麻烦了。
更安全的方式是写得具体一点:
/config/local/
config/*.local.js
或者约定本地配置统一用 .local 后缀:
*.local
*.local.json
*.local.js
.gitignore 不是越多越好,也不是越宽越好。
好的忽略规则应该满足两个条件:
- 不提交不该提交的东西。
- 不误伤项目运行必需的东西。
这两点之间,需要一点边界感。
坑四:忽略目录后,又想保留里面某个文件
很多项目会遇到这种情况:
我们想忽略 logs/ 目录里的所有日志,但希望保留这个目录本身,因为程序启动时需要它存在。
直接写:
logs/
会把整个目录忽略掉,Git 也不会提交空目录。
通常可以这样处理:
logs/*
!logs/.gitkeep
然后在 logs/ 目录下放一个空文件:
logs/.gitkeep
.gitkeep 不是 Git 官方功能,它只是一个约定俗成的占位文件。
它的作用很朴素:让 Git 能提交这个目录。
坑五:不同技术栈的 .gitignore 不一样
一个前端项目、Python 项目、Java 项目、移动端项目,需要忽略的内容是不一样的。
比如 Node.js 项目常见写法:
node_modules/
dist/
build/
.env
.env.local
npm-debug.log*
yarn-debug.log*
pnpm-debug.log*
Python 项目可能是:
__pycache__/
*.py[cod]
.venv/
venv/
.env
.pytest_cache/
.coverage
Java 项目可能是:
target/
*.class
*.log
.idea/
*.iml
通用规则当然可以有,但不要拿一个项目的 .gitignore 无脑复制到另一个项目。
更推荐的方式是:
- 根据技术栈选择模板。
- 再根据项目实际情况删改。
- 团队内保持统一约定。
GitHub 在创建仓库时会提供常见语言的 .gitignore 模板,也可以作为参考。
坑六:把编辑器配置一刀切忽略
很多人会写:
.vscode/
.idea/
这不一定错,但要看团队习惯。
有些编辑器配置是个人偏好,比如窗口布局、插件缓存、本地路径,这些不该提交。
但有些配置对团队是有价值的,比如:
- 统一格式化规则
- 推荐插件
- 调试配置
- TypeScript SDK 路径
- 保存时自动格式化设置
以 VS Code 为例,可以选择忽略大部分 .vscode,但保留关键配置:
.vscode/*
!.vscode/settings.json
!.vscode/extensions.json
!.vscode/launch.json
不过这也有前提:团队真的需要这些配置,并且内容不会绑定某个人的本机路径。
否则提交进去,反而会制造新的混乱。
坑七:没有区分“项目忽略”和“个人忽略”
不是所有忽略规则都应该写进项目 .gitignore。
比如你个人电脑上的系统文件:
.DS_Store
Thumbs.db
或者你自己的编辑器临时文件。
这些可以写进项目里,但如果团队成员使用的系统和工具差异很大,.gitignore 很快会变成一个大杂烩。
这时候可以用 Git 的全局忽略文件。
配置方式大概是:
git config --global core.excludesfile ~/.gitignore_global
然后把个人环境相关的规则放进去。
项目 .gitignore 更适合放:
- 项目依赖
- 构建产物
- 本地环境变量
- 测试缓存
- 运行日志
- 团队共同认可不该提交的文件
个人 .gitignore_global 更适合放:
- 操作系统临时文件
- 编辑器个人缓存
- 自己工具链产生的文件
这样项目会更干净,协作也更舒服。
一个更实用的 .gitignore 示例
假设这是一个常见的前端项目,可以这样写:
# Dependencies
node_modules/
# Build output
dist/
build/
.vite/
.next/
.nuxt/
# Environment files
.env
.env.local
.env.*.local
!.env.example
# Logs
*.log
npm-debug.log*
yarn-debug.log*
pnpm-debug.log*
# Test and coverage
coverage/
.nyc_output/
# Cache
.cache/
.temp/
.tmp/
# Editor
.vscode/*
!.vscode/settings.json
!.vscode/extensions.json
.idea/
# OS
.DS_Store
Thumbs.db
这个示例有几个特点:
- 分类清楚,后续维护方便。
- 忽略敏感配置,但保留
.env.example。 - 忽略构建产物和依赖目录。
- 对编辑器配置做了选择性保留。
当然,这不是万能模板。真正好用的 .gitignore,一定要跟项目实际情况对齐。
判断一个文件该不该忽略,可以问 4 个问题
当你不确定某个文件要不要提交时,可以问自己:
- 这个文件能不能通过代码、命令或依赖重新生成?
- 这个文件是不是只跟我本地环境有关?
- 这个文件里有没有密钥、密码、Token、私有路径?
- 这个文件提交后,会不会给其他同事制造冲突?
如果大多数答案是“是”,那它大概率应该被忽略。
反过来,如果这个文件是项目运行必需的配置模板、团队共享规则、源码的一部分,就不应该随便忽略。
.gitignore 写到最后,其实考验的不是语法,而是你对项目边界的理解。
结尾:别小看这个小文件
.gitignore 看起来只是一个配置文件,但它会影响仓库体积、团队协作、安全风险和新人上手体验。
今天我们讲了三个关键点:
.gitignore只对未被跟踪的文件生效,已经提交过的文件需要用git rm --cached处理。- 敏感文件不要进 Git,尤其是
.env、密钥、Token,一旦提交过就要视为泄露。 - 忽略规则要具体、克制、按项目定制,不要无脑复制模板。
如果你现在手头有一个项目,不妨打开 .gitignore 看一眼:里面有没有已经过时的规则?有没有该忽略却没忽略的文件?有没有不该忽略却被误伤的目录?
.gitignore 写得好,仓库会更干净;写得随便,问题可能迟早在团队协作里爆出来。
.gitignore 常用规则速查表
| 规则 | 中文注释 |
|---|---|
# 注释内容 |
注释行,不会被 Git 当作忽略规则处理 |
*.log |
忽略所有 .log 结尾的日志文件 |
*.tmp |
忽略所有 .tmp 结尾的临时文件 |
.env |
忽略所有名为 .env 的文件 |
/.env |
只忽略项目根目录下的 .env 文件 |
.env.* |
忽略 .env.local、.env.production 等环境变量文件 |
!.env.example |
不忽略 .env.example,常用于提供环境变量模板 |
node_modules/ |
忽略 node_modules 依赖目录 |
dist/ |
忽略 dist 构建产物目录 |
build/ |
忽略 build 构建产物目录 |
coverage/ |
忽略测试覆盖率报告目录 |
.cache/ |
忽略缓存目录 |
.vscode/ |
忽略 VS Code 配置目录 |
.idea/ |
忽略 JetBrains 系列 IDE 配置目录 |
!.vscode/settings.json |
在忽略 .vscode/ 的情况下,保留团队共享的 VS Code 设置 |
logs/* |
忽略 logs 目录下的所有内容 |
!logs/.gitkeep |
保留 logs/.gitkeep,让 Git 能提交空目录 |
**/temp/ |
忽略任意层级下名为 temp 的目录 |
docs/*.pdf |
忽略 docs 目录下一层的 PDF 文件 |
docs/**/*.pdf |
忽略 docs 目录下任意层级的 PDF 文件 |
*.local |
忽略所有 .local 结尾的本地配置文件 |
*.bak |
忽略备份文件 |
.DS_Store |
忽略 macOS 自动生成的系统文件 |
Thumbs.db |
忽略 Windows 自动生成的缩略图缓存文件 |
小结:
.gitignore的规则不难,真正容易出问题的是“写得太宽”或“文件已经被 Git 跟踪”。遇到不生效时,先用git check-ignore -v 文件路径查规则,再用git rm --cached处理已跟踪文件,基本能解决大多数问题。
本文由 楸木 原创,转载请注明出处。