Skip to main content

排查 2 GiB 推送限制

了解如何绕过 2 GiB 推送限制。

在本文中

关于推送限制

GitHub 对于单个推送的最大限制是 2 GiB。 首次尝试上传非常大的存储库、从其他平台导入大型存储库或尝试重写大型现有存储库的历史记录时,可能会达到此限制。

如果达到此限制,可能会看到以下错误消息之一:

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

可以将推送拆分成更小的部分,也可以删除 Git 历史记录并从头开始。 如果您创建了一个超过 2 GiB 的单个提交,并且无法删除 Git 历史记录并从头开始,那么您需要执行交互式变基,以将大型提交拆分为多个较小的提交。

拆分大型推送

可将推送拆分成多个更小的部分,每一部分的大小都应控制在 2 GiB 以内,以避免触及限制。 如果分支超出此大小限制,则可以一次性推送所有分支。 但如果某个分支本身超过 2 GiB,则需要进一步拆分推送内容,一次仅推送少量提交。

  1. 如果尚未配置远程存储库,请将该存储库添加为新的远程存储库。 有关详细信息,请参阅“管理远程仓库”。

  2. 若要在本地存储库中沿着主分支的历史记录查找合适的提交,请运行以下命令:

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

    此命令显示第 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,请执行最终的镜像推送,以确保将剩余的 refs 向上推送。

    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 initgit lfs install,并将新的空 GitHub repository 存储库添加为远程存储库。

  4. 如果已使用 Git 大型文件存储,而且你打算使用的所有 Git LFS 跟踪规则均已在旧文件夹中的 .gitattributes 文件中列出,则该文件应该是复制到新文件夹的第一个文件。 在添加任何其他文件之前,应确保跟踪规则已到位,以免将适用于 Git LFS 的内容提交到常规 Git 存储。

    如果尚未使用 Git LFS,则可以跳过此步骤,也可以设置打算在新文件夹的 .gitattributes 文件中使用的跟踪规则,然后再复制其他任何文件。 有关详细信息,请参阅“配置 Git 大文件存储”。

  5. 将小于 2 GiB 的文件批处理从旧文件夹移动到新文件夹。 移动每个批次后,创建一个提交并在移动下一批次之前推送它。 可以采用更稳妥的方式,将每次推送控制在约 2 GiB。 此外,如果某个文件夹包含适用于 Git LFS 的文件,那么在计算每批次的 2 GiB 限制时,可以忽略这些文件。

清空旧文件夹后,GitHub 存储库应包含所有内容。 如果使用 Git LFS,则应将所有用于 Git LFS 的文件推送到 Git LFS 存储。