排查 GitHub 的 2 GiB 推送限制

了解如何将大型推送拆分处理,避免达到 GitHub 单次推送的 2 GiB 上限。

关于推送限制

GitHub 对单次推送设有2 GiB上限。首次上传非常大的仓库、从其他平台导入大型仓库,或重写大型现有仓库的历史时,可能达到这一限制。

达到限制时,可能看到以下错误之一:

  • fatal: the remote end hung up unexpectedly
  • remote: fatal: pack exceeds maximum allowed size

可以把推送拆成较小部分,或者删除 Git 历史并从头开始。如果单个提交大于2 GiB,而且不能删除历史重新开始,就需要用交互式变基,把大提交拆成多个小提交。

拆分大型推送

将推送拆分成每部分小于2 GiB的批次,就能避免达到上限。如果一个分支在限制内,可以一次推送整个分支;如果单个分支超过2 GiB,需要进一步拆分,每次只推送少量提交。

  1. 尚未配置远程仓库时,先将目标仓库添加为新的远程。详见管理远程仓库:添加远程。

  2. 在本地仓库中沿主分支历史寻找适合分批推送的提交:

    git log --oneline --reverse refs/heads/BRANCH-NAME | awk 'NR % 1000 == 0'
    

    这条命令显示每第1000个提交,而不是只显示第1000个。增大或减小1000可以调整步长。

  3. 将找出的提交逐个推送到 GitHub 托管的仓库:

    git push REMOTE-NAME +<YOUR_COMMIT_SHA_NUMBER>:refs/heads/BRANCH-NAME
    

    如果仍报 remote: fatal: pack exceeds maximum allowed size,减小步骤2的步长后再试。

  4. 对步骤2找出的每个提交,重复同样的处理。

  5. 如果这是首次把仓库推送到 GitHub,最后做一次镜像推送,确保剩余引用也被推送:

    git push REMOTE-NAME --mirror
    

    如果仍然太大,需要使用相同步骤,分阶段推送其他分支。

熟悉该流程后,可以自动执行步骤2–4。例如:

step_commits=$(git log --oneline --reverse refs/heads/BRANCH-NAME | awk 'NR % 1000 == 0')
echo "$step_commits" | while read commit message; do git push REMOTE-NAME +$commit:refs/heads/BRANCH-NAME; done

从头开始

如果仓库没有历史,或者初始提交本身超过2 GiB,且你接受重置 Git 历史,也可以从头开始。

  1. 在本地副本中删除隐藏的 .git 文件夹,移除以往所有 Git 历史,让它恢复为仅包含文件的普通文件夹。

  2. 新建一个空文件夹。

  3. 在新文件夹运行 git init 和 git lfs install,并将新的空 GitHub 仓库添加为远程。

  4. 如果已使用 Git Large File Storage(Git LFS),而且旧文件夹的 .gitattributes 已列出新仓库所需的全部跟踪规则,首先复制这个文件。添加其他任何文件前,先确保跟踪规则就位,避免应进入 Git LFS 的内容被提交到常规 Git 存储。

    如果尚未使用 Git LFS,可以跳过这一步;也可以先在新文件夹的 .gitattributes 中设置需要的规则,再复制其他文件。详见配置 Git 大文件存储。

  5. 每次把小于2 GiB的一批文件从旧文件夹移到新文件夹。每批移动后,创建提交并推送,再处理下一批。采取稳妥方式时,应把每次推送控制在上限附近且留出余量。如果文件夹中有应进入 Git LFS 的文件,在考虑每批次2 GiB限制时,可以不计入这些 LFS 文件内容。

旧文件夹清空后,GitHub 仓库应包含所有内容。使用 Git LFS 时,所有对应文件都应已经推送到 Git LFS 存储。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容