核心问题是git为每个已追踪大文件执行完整sha-1计算、状态检查及合并预判,导致i/o暴增;解决需先用git rm --cached移出索引并提交,再配合.gitignore隔离,而非仅调参或清理工作区。

Git 切换分支慢,如果确认是大文件导致的,核心问题不在“怎么切”,而在“Git 正在为每个大文件做完整内容比对和状态检查”。不清理或隔离这些文件,调参数、换命令都只是缓解表象。
为什么大文件会让 git checkout 变慢
Git 默认把所有 tracked 文件都纳入工作区状态管理。一旦有几十 MB 以上的二进制文件(如 dist.zip、model.bin、docs.pdf),每次切换分支时:
- Git 要逐个计算它们的 SHA-1(哪怕没改)
- 要检查是否被修改(stat + read 整个文件)
- 如果目标分支里同名文件内容不同,还要做内容合并预判
- IDE(如 IDEA、VSCode)还会额外触发文件监听器扫描,放大 I/O 压力
这不是网络或 CPU 问题,是设计使然——Git 不擅长处理大文件,它本就不是为这个设计的。
立刻见效:用 .gitignore 隔离已存在的大文件
很多人以为 .gitignore 只对新文件生效,其实只要文件没被 track,加进去就能切断 Git 对它的感知。但注意:如果文件已经在历史中被 commit 过,.gitignore 不会自动“卸载”它。
- 先查哪些大文件已被跟踪:
git ls-files -l | sort -nr | head -20(按字节倒序列出前 20 个) - 把路径写进
.gitignore,比如:dist/、**/*.zip、data/large-model.bin - 执行:
git rm --cached -r dist/(只从索引移除,保留本地文件) - 再
git commit -m "remove large build artifacts from tracking"
这步做完,下次 git checkout 就不再碰这些文件了——速度提升通常立竿见影。但注意:--cached 是关键,漏掉就会删掉你磁盘上的文件。
长期方案:用 git-lfs 替代原生存储
如果某些大文件必须版本化(比如设计稿、测试数据集),git-lfs 是唯一靠谱的选择。它把文件实体替换成指针,Git 只管指针,LFS 后台按需下载。
- 安装 LFS:
git lfs install(仅需一次,作用于当前仓库) - 追踪后缀:
git lfs track "*.psd"、git lfs track "assets/**.fbx" - 提交
.gitattributes:git add .gitattributes && git commit -m "track psd with lfs" - 后续所有
git add都会自动走 LFS,git checkout只拉指针,不读大文件
注意:LFS 不是“开箱即用”。首次 clone 或 checkout 时仍需 git lfs pull 才能拿到真实文件;团队成员也得装 LFS 客户端,否则看到的是纯文本指针。
别踩坑:git clean -f 和 git reset --hard 都不能解决根本问题
有人试过 git clean -f 清临时文件、git reset --hard 强刷工作区,结果发现切换还是慢——因为这些命令不改变 Git 对“哪些文件该被管理”的定义。只要大文件还在 index 里,Git 就照常检查。
-
git clean -f只清 untracked 文件,对 tracked 的大文件完全无效 -
git reset --hard会重置工作区和 index,但紧接着git checkout还是要重新加载那些大文件 - 真正要动的是
index(用git rm --cached)或历史(用git filter-repo彻底删除)
如果你已经往历史里塞了几百 MB 的日志文件,.gitignore + --cached 只能防新增,旧记录还在对象库中拖慢整个仓库——这时候就得上 git filter-repo 做历史瘦身,但那是另一层复杂度了。











