如何让Git忽略已跟踪文件的改动?

文章导读
遇到这个问题,先别急着往 .gitignore 里加路径。因为 Git 对“已跟踪文件”的处理逻辑和“未跟踪文件”完全不同,先确认文件到底有没有被跟踪,再决定下一步。
📋 目录
  1. 如果只是不想看本地改动:skip-worktree
  2. assume-unchanged 和 skip-worktree 别混用
  3. 如果是敏感文件:彻底移出版本库
  4. 操作后怎么验证,以及要注意的边界
A A

遇到这个问题,先别急着往 .gitignore 里加路径。因为 Git 对“已跟踪文件”的处理逻辑和“未跟踪文件”完全不同,先确认文件到底有没有被跟踪,再决定下一步。

.gitignore 文件只能影响尚未被 Git 跟踪的文件。一旦某个文件已经被 git add 提交过,Git 就会一直监控它的状态,无论 .gitignore 里写了什么都不会再起作用。判断一个文件是否已被跟踪,可以运行 git ls-files | grep 。如果输出中包含该文件,就说明它已经进入版本库索引。此时唯一要做的不是改 .gitignore,而是先决定这个文件是应该继续留在版本库里、只是暂停跟踪改动,还是干脆从版本库里移除。

如果 git ls-files 的 grep 结果没有输出,说明这个文件还没被跟踪,这时在 .gitignore 里加一行就能彻底忽略它。如果输出中包含文件名,说明它已经进了版本库索引,那就要在下面两条路里选一条:暂停跟踪改动,或者干脆移出版本库。

如果只是不想看本地改动:skip-worktree

这类场景很常见:项目需要提交一份默认配置文件,但每个开发者在本地都要修改其中一部分参数,又不希望每次 status 都提示。这时用 git update-index --skip-worktree 合适。

对于"配置文件我要保留在仓库里,但本地要改,且不希望每次都被 git status 提示"的场景,git update-index --skip-worktree 是最合适的做法。执行后,Git 会忽略该文件在本地工作区的所有改动,git status 和 git diff 都不再显示它。想要恢复监控时,执行 git update-index --no-skip-worktree 即可。这种方法适合那些部署时需要但开发时会被本地环境覆盖的配置文件,比如 application.yml 的一部分参数。

如何让Git忽略已跟踪文件的改动?

操作要点是:先确认文件路径正确,然后执行命令。执行后立刻看 git status 确认该文件不再出现在改动列表里。如果后续要恢复监控,记得用 --no-skip-worktree。这个标记只存在本地索引里,不会跟着 commit 推送,所以同事的仓库不受影响。但它对目录无效,只能指定具体文件路径。

assume-unchanged 和 skip-worktree 别混用

git update-index --assume-unchanged 和 skip-worktree 在命令形式上看几乎一样,但实际语义不同。assume-unchanged 的设计初衷是告诉 Git"这个文件很大,我认为它没有改动,请跳过检查"来提升性能,主要用于只读的大文件。如果文件真的被改了,Git 在合并且发现索引与工作区不一致时会报错。所以对于"我就是要改这个文件但不想让 Git 管"的场景,应该优先用 skip-worktree,而不是 assume-unchanged。两个命令的恢复方式分别是 --no-assume-unchanged 和 --no-skip-worktree,不要搞混。

从命令形式上看两者很像,但恢复参数不一样,而且发生合并时行为也不同。如果你只想让 Git “别看”这个文件的改动,用 skip-worktree 更安全。一旦误用 assume-unchanged 并且本地又改了文件,后面拉取远程更新时 Git 会发现索引和工作区不一致,报错时处理起来很被动。可以先用 git ls-files -v 看看现有标记,再决定改哪个。

如何让Git忽略已跟踪文件的改动?

如果是敏感文件:彻底移出版本库

如果文件里是数据库密码、临时脚本、本地生成产物,或者压根不应该让所有项目成员都看到,那暂停跟踪改动就不够了,应该从版本库里移除。操作顺序是:先把这个文件路径写进 .gitignore,再执行 git rm --cached <文件路径>。这里的 --cached 一定不能漏,它只删除索引里的记录,保留本地文件。然后提交这次变更。提交之后,这个文件只存在于已有克隆的本地,新克隆的仓库里不会再有它。要注意,这个操作会改变仓库结构,如果团队其他人还在用这个文件,需要提前说一声。

例如,要移出一个 config.local.yml,可以这样操作:

echo 'config.local.yml' >> .gitignore
git rm --cached config.local.yml
git commit -m 'stop tracking config.local.yml'

操作后怎么验证,以及要注意的边界

验证是否打上标记,用 git ls-files -v。输出里第一个字符如果是 S,说明是 skip-worktree;如果是 h,说明是 assume-unchanged;正常跟踪显示为 H。如果发现标记打错了,对单个文件用 git update-index --no-skip-worktree 或 --no-assume-unchanged 取消。注意 skip-worktree 不能真正阻止远程变更合入。同事如果更新了仓库里这个被忽略的文件,你执行 git pull 或 git merge 时,Git 依然会尝试合并到本地,冲突时被忽略的文件可能意外出现在暂存区。所以这个命令适合短期临时使用,不适合长期依赖。也不要对目录执行 git update-index --skip-worktree . 这样的命令,它只能作用于单个文件,实际使用时先把文件路径写完整。

另外,如果你打算用 .gitignore 来忽略已跟踪文件,唯一的生效方式就是先解除跟踪。文件只要还在版本库里一天,.gitignore 就不会管它。正确处理顺序是:先做决定,再改 .gitignore,最后再执行具体的索引操作。