处理历史提交中的大文件导致推送失败
适用场景:本地历史中曾提交过大文件(超过平台限制),后续虽然有新提交,但历史记录仍携带这些文件,导致推送被拒绝。需要从所有历史中彻底移除这些大文件,同时保留后续的正常提交。
所需工具:git-filter-repo(安装:sudo apt install git-filter-repo 或 pip install git-filter-repo)
第一步:重写历史,删除指定的大文件/目录
git filter-repo --path path/to/large-file --path path/to/large-dir/ --invert-paths --force
--path:指定要保留的路径(可重复使用)。--invert-paths:反转含义,即排除这些路径,从所有历史提交中删除它们。--force:当本地仓库不是全新克隆时,强制重写历史。
示例:若需要删除根目录下的
large.zip和bin/整个目录,则写为--path large.zip --path bin/ --invert-paths
第二步:清理无用对象,使删除真正生效
git reflog expire --expire=now --all
git gc --prune=now --aggressive
作用:重写历史后,旧的大文件对象仍残留在 .git/objects 中,并被 reflog 引用。这两条命令强制清空所有 reflog 记录,并立即修剪不可达的对象,物理删除这些大文件,从而真正缩小仓库体积。若不执行此步,推送时仍会尝试上传已删除的大文件,导致失败。
第三步:检查并重新添加远程仓库(若丢失)
git remote -v # 查看现有远程配置
git remote add origin <仓库地址> # 若缺失则重新添加
git remote -v # 确认
注:
filter-repo可能会清除远程配置,必要时重新设置。
第四步:强制推送重写后的分支
git push origin <分支名> --force
使用 --force 是因为本地历史已被重写,需要覆盖远程分支。
注意事项:
- 操作前建议备份
.git目录(cp -r .git /tmp/backup.git)。 - 强制推送会改变远程历史,若多人协作,需提前通知团队成员。
- 如果还有其他大文件,可在第一步中一并列出。
分支影响:默认重写全仓库历史(所有分支和标签)。若只想测试特定分支,可加
--refs <分支名>,但这样无法彻底回收大文件空间,后续合并时易复发。建议在操作前备份全仓库,并统一处理所有分支。