技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTGIT

.gitignore 文件——如何在 Git 中忽略文件和文件夹译

所属馆藏
Git
文件格式
Markdown
原始路径
git/02-gitignore 文件——如何在 Git 中忽略文件和文件夹[译]
本文目录15 个章节
  1. 前言
  2. 什么是 .gitignore 文件?
  3. 如何创建 .gitignore 文件?
  4. .gitignore 中通常应该包括什么?
  5. .gitignore 模式语法
  6. 否定模式 !:为忽略规则添加例外
  7. 规则优先级和作用范围
  8. 如何验证一个文件是否被忽略?
  9. .gitignore 不会影响已经跟踪的文件
  10. 强制添加被忽略的文件
  11. 清理未跟踪和被忽略的文件
  12. 常见问题和排查清单
  13. 一个可复用的检查流程
  14. 总结
  15. 参考资料

.gitignore 文件——如何在 Git 中忽略文件和文件夹

Category(分类): git Status: 未知

原文:.gitignore File – How to Ignore Files and Folders in Git

本文保留原文的翻译结构和示例,并根据 Git 官方文档补充模式匹配、规则优先级、调试命令、已跟踪文件处理和敏感信息处理。示例中的 master 可以替换为项目实际使用的 main 或其他默认分支。

前言

Git 是一个流行的分布式版本控制系统。开发人员通过它协作开发、记录项目历史,并在需要时查看差异、回退或恢复以前的版本。

Git 的基本工作方式是:用 git add 把确认过的内容放入暂存区,再用 git commit 保存到本地提交历史,最后根据协作需要使用 git push 推送到远程仓库。

在团队项目中,有些文件不应该提交给其他人,例如操作系统生成的文件、编辑器个人配置、依赖目录、编译产物、日志、临时文件和本地环境变量。.gitignore 就是用来声明这些尚未被 Git 跟踪的路径应该被排除的规则文件。

需要先纠正一个常见误解:.gitignore 不是“删除文件”或“隐藏文件”的命令,也不会从已经存在的提交历史中抹掉文件。它主要影响未跟踪文件是否出现在 git status 中,以及 git add 是否默认添加它们。

本文将介绍:

  • 什么是 .gitignore
  • 如何创建和放置 .gitignore
  • 常见的文件、目录和通配模式;
  • ! 否定规则和规则优先级;
  • 如何检查某个文件为什么被忽略;
  • 如何停止跟踪一个已经提交的文件;
  • 如何安全清理被忽略的构建产物和临时文件。

什么是 .gitignore 文件?

在一个 Git 工作区中,路径通常可以从几个角度描述:

  • 已跟踪(tracked):路径已经进入 Git 的索引,通常曾经被提交过,或者当前已经被 git add 暂存。
  • 未跟踪(untracked):工作区中存在,但还没有进入索引的路径。
  • 被忽略(ignored):符合某条排除规则的未跟踪路径。它仍然存在于磁盘上,只是 Git 默认不把它作为普通未跟踪文件提示,也不会被普通的 git add 添加。
  • 已删除但尚未提交:原来已跟踪的文件从工作区删除后,Git 会把删除显示为工作区变更;这不是“忽略”。

“被忽略”不是与 tracked、untracked 完全并列的永久文件状态。一个文件只要被 git addgit add -f 加入索引,之后即使它匹配 .gitignore,Git 仍会继续跟踪它的修改。

.gitignore 是纯文本文件,里面每一行通常是一条模式:

# 这是注释
node_modules/
*.log
.env

它可以写文件名、目录名、相对路径和通配模式。规则可以放在仓库根目录,也可以放在子目录中;子目录中的 .gitignore 主要影响该目录及其后代路径。

.gitignore.git/info/exclude 和全局排除文件

除了项目中的 .gitignore,Git 还支持其他排除规则来源:

  1. 命令行指定的排除规则:某些底层命令可以通过参数提供规则。
  2. 各级目录中的 .gitignore:适合需要提交并让团队共享的项目规则。
  3. .git/info/exclude:只对当前本地仓库生效,不会被提交,适合个人在这个仓库中的临时文件。
  4. 全局排除文件:通过 core.excludesFile 配置,适合所有仓库都不希望看到的操作系统或个人工具文件。

查看全局排除文件配置:

git config --get core.excludesFile

例如可以设置一个用户级排除文件:

git config --global core.excludesFile ~/.config/git/ignore

不要把项目构建产物写进个人全局排除文件,否则团队其他成员无法获得这条规则;项目规则应该放进仓库中的 .gitignore 并提交。

如何创建 .gitignore 文件?

通常把 .gitignore 放在仓库根目录:

cd 项目根目录
touch .gitignore

以点号开头的文件在 Unix 系统中通常属于隐藏文件,可以使用下面的命令查看:

ls -la

Windows 用户可以在 PowerShell 中创建和查看:

New-Item .gitignore -ItemType File
Get-ChildItem -Force

如果仓库已经存在 .gitignore,不要直接覆盖它。先阅读项目已有规则,再按项目约定补充内容:

git status --short
cat .gitignore

.gitignore 本身通常应该提交到仓库,让所有协作者使用同一套项目规则。只有个人规则才适合放到 .git/info/exclude 或全局排除文件中。

.gitignore 中通常应该包括什么?

应该忽略的是“不应作为项目源文件提交”的内容,而不是所有自己不想看到的文件。常见类别包括:

  • 操作系统生成的文件,例如 macOS 的 .DS_Store、Windows 的 Thumbs.db
  • 编辑器或 IDE 的个人配置,例如 .idea/、某些 .vscode/ 用户配置;
  • 依赖目录,例如 Node.js 的 node_modules/
  • 编译产物和构建目录,例如 dist/build/target/,但要先确认项目是否需要提交构建产物;
  • 临时文件、缓存和日志,例如 *.log.cache/
  • 本地环境配置,例如 .env.env.local,其中可能含有密码、令牌和 API 密钥;
  • 覆盖率报告、测试快照临时目录和运行时 PID 文件。

一个通用示例:

# 操作系统文件
.DS_Store
Thumbs.db

# 日志和临时文件
*.log
*.tmp
*.swp

# Node.js 依赖和常见构建产物
node_modules/
dist/
build/
coverage/

# 本地环境变量,不要提交真实密钥
.env
.env.*
!.env.example

上面的规则只是模板,不能机械复制到所有项目:

  • 某些项目需要提交 dist/,例如发布静态文件的仓库;
  • package-lock.jsonpnpm-lock.yamlyarn.lock 等依赖锁文件通常应该提交,以保证安装结果一致;
  • .vscode/ 中可能有团队共享的 settings.json、任务或调试配置,可以只忽略个人文件而不是整个目录;
  • .env.example 可以提交变量名和示例值,但不能放真实密码或令牌。

Node/Nuxt 项目的示例

以常见的 Node.js/Nuxt 项目为例,可以从下面的规则开始,再根据仓库实际情况调整:

node_modules/
.nuxt/
.output/
.nitro/
dist/
coverage/
*.log
.env
.env.*
!.env.example
.DS_Store
Thumbs.db

不要因为某个目录“看起来是生成的”就直接忽略;先确认它是否属于源码、是否需要用于部署,以及团队是否已有统一规则。

.gitignore 模式语法

Git 的 ignore 模式不是普通 shell 命令。每行规则都会经过 Git 的模式匹配处理,常见规则如下。

空行和注释

空行不匹配任何路径,可以用来分组。以 # 开头的行是注释:

# 依赖
node_modules/

# 日志
*.log

如果文件名本身以 # 开头,需要用反斜杠转义:

\#重要说明.txt

规则开头的 ! 有特殊含义。如果文件名本身以 ! 开头,也要使用反斜杠转义:

\!important.txt

行尾空格通常会被忽略。如果文件名或模式确实需要行尾空格,需要用反斜杠转义;实际项目中应尽量避免难以看见的尾随空格。

忽略仓库根目录下的一个文件

如果只想忽略仓库根目录下的 text.txt

/text.txt

开头的 / 表示相对于当前 .gitignore 所在目录的根位置。根目录 .gitignore 中的 /text.txt 不会匹配子目录里的 text.txt

忽略某个相对路径

如果根目录下有 test/text.txt,可以写:

/test/text.txt

在根目录 .gitignore 中,下面这种带斜杠的写法也表示相对路径:

test/text.txt

如果这条规则写在 test/.gitignore 中,路径的相对基准则会变成 test/,因此每个 .gitignore 文件都应结合它所在的目录理解。

忽略任意位置同名的文件或目录

如果模式中没有斜杠,通常可以匹配任意层级的同名文件或目录:

text.txt

它可以匹配:

text.txt
src/text.txt
test/fixtures/text.txt

如果只想匹配仓库根目录的文件,应写成 /text.txt

忽略目录

在目录名后面加 /,表示匹配目录及其内容:

test/

根目录 .gitignore 中的 test/ 会匹配任意层级名为 test 的目录。只想忽略仓库根目录的 test 目录,可以写:

/test/

没有结尾斜杠的 test 则可能同时匹配名为 test 的文件和目录:

test

前缀匹配:*

如果想忽略所有名称以 img 开头的文件或目录,可以使用:

img*

这条没有斜杠的规则可以匹配不同目录中的 img.pngimage-cache/ 等名称。* 在普通模式中不会跨越路径分隔符;如果需要表达多层目录,应使用路径或 **

后缀匹配:*.md

要忽略所有 Markdown 文件,可以写:

*.md

这条没有斜杠的模式可以匹配仓库任意层级的 README.mddocs/guide.md 等文件。

原文中曾把 .md 单独作为“所有 Markdown 文件”的规则,这是错误的:.md 只会匹配名为 .md 的文件或目录,不等于“所有以 .md 结尾的文件”。需要通配符 *.md

路径中的通配符

常见的 ? 匹配一个字符,[0-9] 匹配字符范围:

file?.tmp
cache-[0-9].json

** 用于表达跨目录层级的匹配。例如:

# 任意层级的 docs 目录中的临时文件
docs/**/tmp/

# logs 目录下的所有内容,无论嵌套多少层
logs/**

# 根目录 a 目录下的任意层级 .cache 目录
/a/**/.cache/

对于简单场景,优先使用清晰的目录和扩展名规则,不要为了“看起来高级”而滥用 **

否定模式 !:为忽略规则添加例外

如果先忽略一个模式,再使用以 ! 开头的模式,可以重新包含某个路径:

# 忽略所有 Markdown 文件
*.md

# 但保留根目录的 README.md
!/README.md

规则通常按顺序处理,同一层级中后出现的匹配规则可以覆盖前面的规则。因此例外规则要放在被忽略规则之后。

被忽略的父目录不能直接重新包含文件

下面的写法通常无法达到预期:

# 整个 test 目录被排除
test/

# 试图重新包含其中的文件,但 Git 不会继续遍历被排除的目录
!test/example.md

原因是 Git 为了性能不会遍历已经被排除的目录,因此后面的文件例外规则没有机会生效。

如果希望保留 test/example.md,可以不要排除整个 test/ 目录,而是排除其内容:

# 不排除 test 目录本身,让 Git 可以继续遍历
test/*

# 重新包含指定文件
!test/example.md

如果还要保留更深层级的目录,也要确保通往目标文件的每一级目录没有被整体排除。复杂规则应使用 git check-ignore -v 验证,而不要只凭猜测。

例外规则的常见写法

例如忽略构建目录,但保留一个说明文件:

build/*
!build/README.md

如果使用的是 build/,则目录本身已经被排除,!build/README.md 不能直接把里面的文件重新包含。此时可以改写规则,或者把说明文件放到没有被排除的目录中。

规则优先级和作用范围

当多个规则同时匹配时,需要考虑规则来源和顺序。一般可以按下面的方向理解:

  • 命令行提供的排除规则优先级最高;
  • .gitignore 规则按目录层级参与匹配,越靠近目标文件的规则通常越具体;
  • 仓库级 .git/info/exclude 用于本地仓库而不共享;
  • core.excludesFile 提供用户级全局排除规则;
  • 在同一层级和同一来源中,后出现的匹配规则通常覆盖前面的规则。

不要把不同来源的规则混在一起排查。一个文件没有出现在 git status 中,可能是项目 .gitignore、某个子目录 .gitignore.git/info/exclude 或全局排除文件造成的。

可以使用 git check-ignore 直接查看命中的规则。

如何验证一个文件是否被忽略?

使用 git status

普通状态只显示未跟踪但未被忽略的文件:

git status --short

如果希望连被忽略的文件也显示:

git status --short --ignored

输出中的 !! 通常表示路径被忽略,例如:

!! .env
!! node_modules/

使用 git check-ignore -v

这是定位规则来源最有用的命令之一:

git check-ignore -v -- .env

可能得到类似输出:

.gitignore:12:.env    .env

它会告诉你:命中的是哪个规则文件、第几行以及具体模式。检查多个路径时可以一起传入:

git check-ignore -v -- .env dist/ app.log

默认情况下,已经被跟踪的文件不会被 git check-ignore 显示,因为 ignore 规则不适用于已跟踪路径。如果想排查“为什么这个文件被 git add . 添加了”的模式问题,可以使用:

git check-ignore -v --no-index -- path/to/file

--no-index 只适合调试匹配规则,不会把文件从索引中删除。

查看所有被忽略的未跟踪文件

可以结合 git ls-files 查看:

git ls-files --others --ignored --exclude-standard

其中 --exclude-standard 会采用 .gitignore.git/info/exclude 和全局排除规则。查看结果前要注意:被忽略的目录可能只显示目录名,不一定列出其中每一个文件。

.gitignore 不会影响已经跟踪的文件

Git 官方的排除规则主要作用于有意保持未跟踪的路径。假设某个文件已经被提交:

git add config.local.json
git commit -m "add local config"

之后再把它写进 .gitignore

config.local.json

此时 Git 仍然会跟踪它的后续修改,因为它已经在索引中。可以用下面的命令确认:

git ls-files -- config.local.json
git status --short

如果目标是“保留本地文件,但停止跟踪并以后忽略”,需要把它从索引中移除。

停止跟踪单个文件但保留本地文件

例如误提交了 .env

# 先加入项目忽略规则
echo ".env" >> .gitignore

# 只从索引删除,保留工作区文件
git rm --cached -- .env

# 提交规则和取消跟踪动作
git add .gitignore
git commit -m "chore: stop tracking local environment file"

--cached 的含义是只更新索引,不删除工作区文件。原文中的 -cached 少了一个连字符,正确写法是 --cached

如果希望从索引和工作区都删除文件,可以省略 --cached

git rm -- .env

但这不会自动清理已经存在的历史提交,也不会阻止别人从旧提交中看到它。

停止跟踪整个目录

如果已经提交了构建目录或依赖目录,需要谨慎地从索引移除:

# 先在 .gitignore 中加入对应规则,例如 dist/
echo "dist/" >> .gitignore

# 只从索引移除,保留工作区目录
git rm -r --cached -- dist/

git add .gitignore
git commit -m "chore: stop tracking generated files"

执行前先用 git statusgit diff --cached 检查范围。不要为了“重新应用 .gitignore”而对整个仓库盲目执行破坏性命令。

文件已经包含敏感信息怎么办?

.env 加入 .gitignore 只能防止未来再次被普通 git add 添加,不能让已经泄露的密码、令牌或私钥失效。应按下面顺序处理:

  1. 立即吊销、轮换或删除泄露的凭据;
  2. 确认当前分支、远程仓库、代码评审和构建日志中是否仍有暴露;
  3. 如果需要从历史中删除,使用团队认可的历史清理工具(例如 git filter-repo 或平台提供的密钥清理流程);
  4. 历史改写后通知所有协作者重新同步,并检查其他克隆和缓存。

示意命令如下,执行前必须先阅读工具文档、备份仓库并取得团队同意:

# 示例:从历史中删除某个路径,命令会改写提交 ID
git filter-repo --path .env --invert-paths

上面命令前不需要多余空格。历史清理不是 .gitignore 的替代品,也不是发现密钥后只需要做的一步。

强制添加被忽略的文件

有时某个文件符合忽略规则,但确实需要提交,例如一个项目模板文件:

git add --force .env.example

更推荐从根本上调整规则,让需要提交的文件通过否定模式被明确包含:

.env.*
!.env.example

git add -f 会绕过忽略规则,使用后仍应检查 git diff --staged,避免误把真实密钥或大型生成文件加入提交。

清理未跟踪和被忽略的文件

.gitignore 只是不显示或不默认添加文件,并不会删除磁盘上的文件。如果要清理构建产物,可以使用 git clean,但它是破坏性命令:

# 预览将删除的未跟踪文件,不实际删除
git clean --dry-run

# 预览未跟踪目录
git clean --dry-run -d

# 只预览被忽略的文件和目录
git clean --dry-run -d -X

# 预览所有未跟踪文件,包括被忽略的文件
git clean --dry-run -d -x

确认预览结果无误后,才考虑执行:

# 删除未跟踪文件和目录
git clean -f -d

# 只删除被忽略的未跟踪文件和目录
git clean -f -d -X

不要把 git clean -f -d -x 当作日常清理命令;它会连被忽略的依赖、环境文件和构建缓存一起删除。执行前建议备份本地数据,并先使用 --dry-run。很多 Git 配置默认要求提供 -f,这是为了避免误删。

常见问题和排查清单

为什么写了 .gitignore,文件仍然出现在状态中?

按下面顺序检查:

  1. 文件是否已经被跟踪?如果是,需要 git rm --cached 后再提交;
  2. 忽略规则的相对路径是否正确?根目录规则和子目录规则的基准不同;
  3. 是否忘记了目录末尾的 / 或文件扩展名开头的 *
  4. 后面的规则或 ! 是否重新包含了该文件;
  5. .git/info/exclude 或全局排除规则是否与项目规则冲突;
  6. 使用 git check-ignore -v --no-index -- path 查看实际命中的规则。

为什么写了否定规则,例外文件仍然被忽略?

最常见原因是父目录本身被整体排除。将:

cache/
!cache/keep.json

改为:

cache/*
!cache/keep.json

然后用 git check-ignore -v --no-index -- cache/keep.json 验证。对于多层目录,还要确保中间目录没有被整体排除。

为什么 git add . 没有添加被忽略的文件?

这是正常行为。git add 默认不会添加被忽略的文件;可以确认规则,或者在明确需要时使用:

git check-ignore -v -- path/to/file
git add --force -- path/to/file

不要为了省事对整个目录执行 git add -f .,这可能把日志、缓存和敏感信息全部加入暂存区。

空目录为什么没有被 Git 提交?

Git 主要跟踪文件和文件内容,不会单独跟踪空目录。可以放入一个有明确用途的占位文件,例如 .gitkeep,但 .gitkeep 不是 Git 的特殊文件名,只是社区惯例:

mkdir -p runtime/uploads
: > runtime/uploads/.gitkeep
git add runtime/uploads/.gitkeep

如果目录运行时会产生用户上传内容,应同时使用 .gitignore 忽略真实文件,并只提交占位文件:

runtime/uploads/*
!runtime/uploads/.gitkeep

全局忽略规则会不会影响团队?

会影响你本地的命令输出,但不会自动影响其他协作者。个人全局规则适合 .DS_Store、编辑器临时文件等;项目构建目录、依赖目录和环境模板等团队规则应提交到项目 .gitignore

一个可复用的检查流程

修改 .gitignore 后,可以按下面流程验证:

# 查看规则文件本身和工作区状态
cat .gitignore
git status --short

# 查看被忽略的路径
git status --short --ignored

# 确认具体文件命中了哪条规则
git check-ignore -v --no-index -- .env dist/app.js logs/app.log

# 检查暂存区是否包含了不该提交的内容
git diff --staged

# 如果要清理,先预览,不要直接执行删除
git clean -ndX

提交前尤其要检查:

  • .env、私钥、PAT、云服务密钥和数据库密码;
  • node_modules/、构建产物、缓存和日志;
  • 是否误用了过于宽泛的 *.md*.json* 规则;
  • 是否把团队需要共享的锁文件、配置模板或迁移脚本忽略了;
  • 否定规则是否真的让目标文件重新被包含。

总结

.gitignore 是项目规则文件,用来排除不应被 Git 默认跟踪的未跟踪路径。它不是删除命令,也不能改变已经进入索引的文件状态,更不能从历史中消除已经泄露的秘密。

核心命令可以归纳为:

# 检查规则和状态
git status --short --ignored
git check-ignore -v -- path/to/file

# 停止跟踪但保留本地文件
git rm --cached -- path/to/file

# 必须提交被忽略文件时明确强制添加
git add --force -- path/to/file

# 清理前先预览
git clean -ndX

最重要的实践是:项目规则写入 .gitignore 并提交,个人规则写入 .git/info/exclude 或全局排除文件;使用 git check-ignore -v 定位问题;处理密钥时先轮换凭据,再考虑历史清理。

参考资料

感谢阅读,happy coding :)

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS