【问题标题】:How to reduce the size of the remote repo by deleting size-hungry branch?如何通过删除 size-hungry 分支来减小远程仓库的大小?
【发布时间】:2018-12-05 23:26:37
【问题描述】:

在我们的 git repo 中,其中一个分支包含已提交并推送到远程 repo 进行测试的二进制文件,但这导致了填充我们 repo 大小的意外后果。在做了一些研究here 和here 之后,提供了一些解决方案差异很大的场景。我想知道我们是否有一个更简单的方案来避免我们可能会利用的“git push --all --force”(这需要更多的协调)。

在我们的例子中,我们不再关心分支是否存在,并且完全可以删除它(连同它的历史等)。我们可以将所涉及的工作重新提交到另一个分支。由于分支尚未合并到其主分支,我们是否可以完全删除分支。假设在提交的二进制文件的分支中引用是自包含的,有没有更简单的解决方案?

根据研究,提出了以下解决方案:

但是,他们假设读者想要保留历史记录并因此删除有问题的二进制文件,重写历史记录和/或问题仍然本地化到本地存储库。如果问题是远程的,则需要修复本地,然后将 --all 推送到远程。

在这种情况下,我们已经删除了分支并在一个新的分支上重新提交了工作,但是大小还没有改变,我们还需要做什么呢?由于数据已本地化到已删除的分支并且允许删除该分支,是否有更简单的解决方案?我们也不确定 git 是否会以某种方式保留二进制文件,以便在历史的其他部分保留对它们的引用。远程服务器是否需要垃圾收集?修剪参考文献?

【问题讨论】:

    标签: git github git-branch git-repo git-history


    【解决方案1】:

    一般来说,删除分支是正确的答案。但是这里有很多繁琐的小旋钮可以转动。其中一些,您可以等待(大约一个月)并避免处理。但是,如果您不想等待存储库的各个副本自行缩小:

    在这种情况下,我们已经删除了分支并在新分支上重新提交了工作,但大小还没有改变......

    首先,请记住 Git 是自然分布的。每个存储库(至少在原则上)是完全独立的,并且独立于其他所有存储库。因此,当您说 存储库尚未精简时,显而易见的第一个问题是:哪个?

    您对任何一个存储库所做的任何更改都不会影响任何其他存储库,至少在您交叉连接它们两个并告诉一个从另一个获取新工作或将新工作推送到另一个之前不会.如果您在测试克隆中执行所有这些操作,那很好,只需记住测试克隆的结果将特定于该克隆。

    下一个问题是 Git,就其本质而言,“想要”对所有内容进行更多的复制。提交就像一些病毒或疾病:将一个 Git 连接到另一个 Git,没有提交的 Git 现在有了它们。 确实有提交的 Git,仍然有提交。当您最终从(例如)16 个克隆中删除提交时,对于任何地方的任何人来说,确实在他们的克隆中有提交的人都会很容易意外地重新引入它们到固定的克隆,它们将从那里传播回所有其他克隆。这并不意味着你不能摆脱提交——你现在拥有它们的方式的“只能从一个分支访问”的性质将简化事情很多,因为您只需要确保没有其他人从他们的克隆中恢复或合并该分支。

    对于很多有用的背景,我建议阅读并浏览网站Think Like (a) Git。一旦你消化了那里的内容,缩小存储库的方法是:

    • 确保具有大文件的提交无法访问。在您的特定情况下,删除分支名称可以让您大部分时间到达那里:它们可以从该分支名称以及通过该分支的 reflogs 访问。删除分支也会删除其 reflog,因此该路径现在已被清除。

      仍然可以(可能)到达这些提交的位置在您的HEAD reflog 中。运行git reflog 将显示所有HEAD reflog 条目(默认操作是show,默认显示的reflog 是HEAD)。您可以选择性地删除每个这样的 reflog 条目,例如,git reflog delete,但更容易删除 all 您的 HEAD reflog 条目:

      git reflog expire --expire=now --expire-unreachable=now
      

      请注意,这会删除您恢复其他意外丢失的HEAD 提交的所有能力,因此在执行此操作之前请确保您对此没有问题。您可以省略 --expire=now,因为从您当前的分支中不应该访问特定于已删除分支的提交——我在这里展示了命令的“从轨道上核对它”变体。

    • 然后,运行git gc --prune=now。这是the git filter-branch documentation 中“缩小存储库的清单”的最后一步。

    这将处理重建包文件和/或丢弃包含无法从任何外部名称访问的大文件的松散对象所需的所有各种项目。也就是说,没有外部名称直接或间接指向通过其树或其子树之一指向保存文件的 blob 对象的任何提交。因此,gc 命令将协调删除不需要的对象的其他命令(git repack 和 git prune)。

    (注意:如果您使用.keep 文件来保留旧包,则必须删除那些.keep 文件并允许销毁这些包。但是,如果您这样做,则可能不是首先问这个问题。)

    【讨论】:

    • 谢谢,我会看看你提供的链接。在您的回答中,您似乎指的是本地 git 存储库。如果我们希望我们的服务器 git repo 没有二进制文件并且每个人都遵循它的历史,是否必须区分主服务器和其他所有人?我们是否在服务器 repo 上使用 reflog 和 gc 命令?
    • 服务器通常没有 reflogs,但通常 确实 需要相同的 git gc 运行。为此,请登录服务器,导航到存储库,检查是否存在任何引用日志(运行 git reflog),如果需要,执行任何过期操作,然后以与本地存储库相同的方式运行 git gc。请注意,您的服务器最终会自行运行git gc,但默认--prune 时间是14.days.ago,这意味着大型二进制文件可能会持续一段时间。
    猜你喜欢
    • 2015-05-22
    • 2019-11-26
    • 2021-09-01
    • 2015-09-29
    • 1970-01-01
    • 2021-05-27
    • 2021-04-07
    • 2016-12-28
    • 2021-05-04
    相关资源
    最近更新 更多