git filter-repo 是清理 Git 历史中大文件的可靠方案,需备份后用 --path 或 --strip-blobs-bigger-than 重写历史,再强制推送并通知协作者重新克隆。

git filter-repo 删除历史中指定大文件
Git 仓库体积膨胀,八成是因为某次误提交了 node_modules、dist/ 或几十 MB 的视频/日志文件,且已推送到远程。单纯 git rm 不管用——它只删最新提交,历史记录里文件还躺在对象数据库里。
必须用重写历史的工具,git filter-repo 是目前最可靠的选择(官方已弃用 filter-branch,BFG 也逐渐少维护)。
- 先安装:
pip install git-filter-repo(确保 Python 3.8+) - 运行前务必备份:
git branch backup-before-filter,并确认当前分支是你要清理的(如main) - 删掉所有历史中出现过的某个文件(比如
big.zip):git filter-repo --path big.zip --invert-paths
- 删掉整个目录(如所有
logs/下文件):git filter-repo --path logs/ --invert-paths
- 删掉大于 10MB 的所有文件(谨慎!会匹配到二进制资源):
git filter-repo --strip-blobs-bigger-than 10M
执行完会生成新提交哈希,本地仓库立即变小;但远程仓库不会自动同步——你得强制推送:git push --force --all 和 git push --force --tags。所有协作者必须重新克隆,否则 git pull 会失败。
为什么不能用 git reset --hard + push -f 清理大文件
有人试过:找到含大文件的那次提交,git reset --hard HEAD~n 回退,再 push -f。这看似删了,其实错的——被 reset 掉的提交仍保留在 reflog 和远程引用中,且所有后续提交的 parent 指针仍指向它,Git GC 不会回收其中的对象。仓库体积几乎不变。
GitHub 智能代码审查与 CI/CD 自动化工作流。收到 PR 或代码提交时,自动进行 AI 代码审查(bug/安全/逻辑),并根据审查结果智能生成或推荐 GitHub Actions 工作流。触发词:代码审查、review PR、生成 CI/CD、GitHub Actions。
-
git gc --prune=now --aggressive在这种情况下无效:它只清理“不可达”对象,而 reset 后的对象仍被 reflog 引用 - 即使清空 reflog(
git reflog expire --expire=now --all),旧对象仍可能被远程保留,尤其当别人已 fetch 过 - 真正删除必须让对象彻底从所有提交树中消失,只有
filter-repo这类重写工具能做到
清理后 remote 还很大?检查 reflog 和 remote 的引用
本地 git count-objects -vH 显示体积正常,但 git ls-remote --heads origin 仍能看到旧提交 ID?说明远程仓库没真正丢弃旧对象。
- GitHub / GitLab 默认开启「保留引用」策略:即使你
push -f,旧提交仍可通过 SHA 访问一段时间(GitHub 是 30 天,可手动清理) - GitHub 上需进入 Settings → Danger Zone → “Delete all refs that point to commits that are not reachable from any branch or tag”
- 自建 Git 服务器(如 Gitea、Gitolite)要手动在服务端运行:
git gc --prune=now,且确保receive.denyDeletes未阻止引用删除 - 用
git count-objects -vH对比本地与 clone 新仓库的大小,才能确认是否真正生效
如何预防下次又塞进大文件
靠人肉检查不现实。关键是把检测卡在提交前,而不是事后补救。
- 加 pre-commit 钩子:用
git hooks/pre-commit脚本调用git diff --cached --name-only | xargs ls -lh 2>/dev/null | awk '$5 > 10*1024*1024 {print $NF}',超 10MB 就阻断 - 全局忽略:
git config --global core.excludesfile ~/.gitignore_global,在里面加**/*.log、**/tmp/等模式 - 对已存在的大文件类型(如
.psd、.mov),直接加入项目级.gitignore并运行:git rm --cached *.mov(注意加--cached,否则删工作区) - 长期存大文件?别硬塞 Git,改用
git-lfs,但得全团队统一启用,且远程需支持 LFS
最常被忽略的一点:filter-repo 不会动你工作区的文件,但会重写所有提交——这意味着 CI 缓存、依赖锁定文件(yarn.lock、package-lock.json)的哈希全变,构建可能失败。上线前务必在干净环境中验证全流程。

















