Git 推送失败:远程仓库提示文件超过 100MB 限制的解决方案

问题背景

今天在使用 Git 向 Gitee 推送代码时,遇到了一个令人头疼的错误:

remote: File [28d27cabaf49d93bd17ccbb80e92d4ffa7a31032] size 275.109MB, exceeds quota 100MB
remote: Please remove the file[s] from history and try again
error: failed to push some refs to 'https://gitee.com/xxxx/xxxx.git'

原因是本地仓库的历史中曾经提交过两个超过 100MB 的大文件(分别是 grafana-enterprise_12.4.0_…tar.gz 和 prometheus-3.10.0.windows-amd64.zip),虽然我后来删除了文件并重新提交,但 Git 的历史中仍然保留着这些大文件的记录,导致推送时被 Gitee 的预接收钩子拒绝。

踩坑记录

第一次尝试:直接删除文件后重新提交(失败)

我以为只要把文件删掉,再提交一次删除操作就能解决问题。于是:

# 手动删除文件后
git add .
git commit -m "删除大文件"
git push

第二次尝试:回退提交(失败)

我尝试回退到添加大文件之前的提交:

git reset --mixed HEAD~1      # 撤销最后一次提交
git add .
git commit -m "重新提交(不含大文件)"
git push

还是失败!这是因为虽然当前分支的最新提交已经不包含大文件,但大文件所在的提交对象仍然存在于本地仓库的对象数据库中,并且由于它仍被某些历史引用(比如它可能是更早的提交),推送时依然会被打包进去。

正确的解决方法:彻底重写历史,永久删除大文件记录

要彻底解决这个问题,必须重写整个仓库的历史,从所有提交中移除这两个大文件。可以使用 git filter-branch 或更现代的工具 git filter-repo。

步骤一:找到大文件的具体路径

根据错误信息中的对象 ID(28d27cab…),通过以下命令查找对应的文件路径:

git rev-list --objects --all | grep 28d27cabaf49d93bd17ccbb80e92d4ffa7a31032

本例中找到了两个文件:

  • software/grafana-enterprise_12.4.0_22325204712_windows_amd64.tar.gz
  • software/prometheus-3.10.0.windows-amd64.zip

步骤二:使用 git filter-branch 重写历史

执行以下命令,从所有分支和标签中删除这两个文件:

git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch software/grafana-enterprise_12.4.0_22325204712_windows_amd64.tar.gz software/prometheus-3.10.0.windows-amd64.zip" \
  --prune-empty --tag-name-filter cat -- --all

参数说明:

  • –index-filter:在每次提交的暂存区执行命令,比 --tree-filter 更快。
  • git rm --cached --ignore-unmatch:从暂存区删除文件,如果文件不存在则忽略。
  • –prune-empty:删除因移除文件而变空的提交。
  • –tag-name-filter cat:更新标签指向重写后的提交。
  • – --all:处理所有分支和标签。

命令执行后会重写整个历史,过程中会显示每个被重写的提交。

步骤三:清理本地仓库

重写历史后,原来的大文件对象仍然存在于 Git 的对象数据库中,需要彻底清理:

git reflog expire --expire=now --all
git gc --aggressive --prune=now

步骤四:强制推送到远程

由于历史已被重写,需要使用强制推送覆盖远程分支:

git push origin master --force

步骤五:通知协作者

如果仓库有其他协作者,他们需要重新克隆仓库,或者执行以下命令同步:

git fetch --all
git reset --hard origin/master   # 注意这会丢弃本地所有未推送的修改

预防措施

  • 使用 .gitignore:对于不需要版本控制的大文件,提前添加到 .gitignore 中。
  • 使用 Git LFS:对于需要版本管理的大文件(如二进制包、图片等),配置 Git LFS(Large File Storage)。
  • 提交前检查:可以使用 git diff --stat 或 git status 查看即将提交的文件大小,避免误提交大文件。

总结

操作 命令
查找大文件对象对应的路径 git rev-list --objects --all | grep <对象ID>
从历史中彻底删除文件 git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <文件路径>" --prune-empty --tag-name-filter cat -- --all
清理无效对象 git reflog expire --expire=now --all && git gc --aggressive --prune=now
强制推送 git push origin <分支名> --force

标签:Git, Gitee, 大文件, 错误解决, filter-branch

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐