0

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

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

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

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

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

4

1 回答 1

1

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

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

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

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

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

对于许多有用的背景知识,我建议阅读并通过网站Think Like (a) Git工作。一旦你消化了那里的东西,缩小存储库的方法是:

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

    仍然可以(可能)到达这些提交的位置在您的HEADreflog 中。运行git reflog将向您显示所有HEADreflog 条目(默认操作是show,而要显示的默认 reflog 是 for HEAD)。您可以选择性地删除每个这样的reflog 条目,例如,但是使用以下命令删除所有git reflog deletereflog 条目会更容易:HEAD

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

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

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

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

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

于 2018-12-05T23:57:52.257 回答