git filter-branch 已弃用,官方推荐改用 git-filter-repo;它更快、更安全、默认保留引用日志和标签完整性,需通过 pip3 或系统包管理器安装,并用 --invert-paths 等参数精准清理历史大文件。

git filter-branch 已弃用,改用 git filter-repo
直接运行 git filter-branch 不仅慢、易出错,而且自 Git 2.22 起已被标记为“deprecated”,VS Code 集成终端或命令行中执行会看到警告。官方推荐替代方案是 git filter-repo,它更安全、更快、默认保留引用日志和标签完整性。
你得先安装它:
- macOS:
pip3 install git-filter-repo - Linux(Debian/Ubuntu):
sudo apt install git-filter-repo - Windows(WSL 或 Git Bash):
pip3 install git-filter-repo,确保python3和pip3在 PATH 中
安装后别用 git filter-branch 命令硬扛——哪怕网上教程还这么写,它在大仓库里极可能卡死或损坏 reflog。
怎么精准定位并删除那个超大文件的全部历史痕迹
光删工作区文件没用,Git 远端拒绝推送是因为对象数据库里还存着那个 200MB+ 文件的 blob 和所有相关 commit。必须从整个提交图谱中剥离它。
操作分三步:
- 先查哪个文件最占空间:
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"(取最大的 5 个对象反查路径) - 确认路径无误后,运行:
git filter-repo --path "path/to/big_file.h5" --invert-paths --force(注意--invert-paths表示“只保留其他文件”,即删掉指定路径) - 执行完会输出新 commit hash 映射表,原分支名自动重写(如
main→main-orig),新历史在main上
⚠️ 别跳过 --force:filter-repo 默认拒绝覆盖已有 refs,不加会报错退出。
CNB 云原生构建平台的 Git 操作技能,支持代码克隆、提交、推送、分支管理、Merge Request 管理、流水线触发与结果读取。初次使用需收集用户的 Git 用户名和邮箱。
推送到远端前必须清理本地和协作方的缓存
filter-repo 改写了整个提交历史,这意味着你本地的 origin/main 和远端的 main 已完全分叉。直接 git push 会被拒绝;强制推送(git push --force-with-lease origin main)是必要步骤,但有风险。
关键点在于协作场景下其他人怎么办:
- 所有人必须先备份自己未推送的本地修改(
git stash或另起分支) - 然后执行:
git fetch origin && git reset --hard origin/main(丢弃旧本地历史,拉取你刚强推的新历史) - 再把 stash 应用回来:
git stash pop,解决可能的冲突
如果有人忘了这步,继续基于旧 commit 提交,下次你 pull 会重新引入那个大文件——历史没真删干净。
删完仍被 GitHub/GitLab 拒绝?检查 reflog 和 gc
即使 filter-repo 成功,旧对象仍可能藏在 reflog 或松散对象里,导致 git count-objects -vH 显示巨大体积,远程依然报 “file too large”。
必须手动清理:
- 清空 reflog:
git reflog expire --expire=now --all - 删掉所有 unreachable 对象:
git gc --prune=now --aggressive - 验证是否真清了:
git count-objects -vH输出的size-pack应明显下降;再跑一次git rev-list --objects --all | [same grep]确认路径已不出现在结果中
最后才是 git push --force-with-lease origin main。这个顺序不能乱——否则强推的是一个“看起来干净”但底层仍带大 blob 的仓库。

















