BFG回购清洁剂–替代新鲜克隆

met*_*500 5 git-rewrite-history bfg-repo-cleaner

我本打算在存储库中问这个问题,但是SO似乎是一个更合适的问这个问题的地方。

我能够使用BFG Repo Cleaner(很棒的工具,谢谢!)将我们的.git文件夹大小减少了1GB以上,就我们的存储库而言,这是一个巨大的成功。我还没有将裸露的克隆推到远程,因为我担心在了解推入然后不重新克隆的后果之前提出这些更改。

我了解最佳实践指示,当历史以这种方式改变时,最佳解决方案是执行新克隆。但是,我与一支由50多人组成的团队合作,在超过2GB的存储空间和23k的提交中,在我们的架构下,跨团队的协调非常困难。结果,我有一些问题:

  1. 如果我要推送这些更改的引用,而人们将继续使用现有副本而不是创建新的克隆,后果将是什么?
  2. 如果可行,他们是否需要采取其他措施来减轻这些后果,作为其影响的一部分?
  3. 如果您认为删除的斑点来自历史至少一年且最多三年的历史记录,此建议是否会根本改变?
  4. 最后,鉴于新克隆不包括任何未在上游同步的工作,您是否建议将未跟踪分支从一个克隆转移到另一个的最佳方法?如果已经存在执行此操作的Git命令,那么我很想听听您的见解。

再次感谢您创建了这样一个方便的工具,希望我能完成对我的团队项目有用的工作。在此期间,我将继续尝试使用叉子。

Rob*_*ley 10

前言

在开始讨论之前,让我在活跃的开发人员团队的背景下阐明推荐的Git历史记录清理过程(无论用于清理的技术是BFG Repo-Cleaner还是git filter-branch):

  1. 练习对存储库的本地一次性副本进行几次清理,这样您就可以做到并获得所需的结果,并且知道需要多长时间。
  2. 与您的团队沟通。这是必不可少的,不可避免的(因为Git是专门为抱怨和改写历史而设置的),并且对于任何团队来说都是很好的做法 :-)您需要告诉他们:
    • 为什么要进行清理(例如较小的仓库!)
    • 计划清理-给他们合适的预先警告。
    • 可以在清理开始之前所有工作推到主存储库中-不需要将其合并到主分支,但是所有工作都需要在一个分支或另一个分支上进行。
    • 告知他们清理完成后,他们需要删除其回购的旧副本,并重新克隆新清理的存储库
  3. 当所有工作都推到主仓库后,对主仓库进行镜像克隆。备份此克隆,以便在出现问题时始终可以返回。
  4. 运行清洁程序(使用BFG Repo-Cleaner或较慢的工具,如git filter-branch),并git gc修剪掉死掉的物体。
  5. 当您对清理工作感到满意后,将清理后的历史记录推回主存储库(因为它是一个mirror克隆,所有旧分支/标签将被覆盖为新清理后的历史记录)
  6. 告诉您的团队,现在该删除他们的仓库的旧副本了,并重新克隆已清理的存储库。

因此,对您的问题:

如果发生以下情况,该怎么办:具有旧存储库的用户会从已清理的存储库中提取信息?

如果我要推送这些更改的引用,而人们将继续使用现有副本而不是创建新的克隆,后果将是什么?

坏。根据经验我可以说会有一团糟,人们会感到困惑沮丧

具体来说,在该人的计算机上发生的是该git pull命令将旧的脏历史记录和新清除的历史记录合并在一起,并具有两个较长的不同历史记录(最初与您历史记录中的第一个“脏”提交不同,在您的情况下为3年前)以一种全新且令人困惑的合并提交方式加入在一起。用户很少清楚这种情况是否发生过-大多数Git日志可视化工具都不会以可能使其明显的方式呈现这种情况-如果您很幸运,用户可能会说“我现在每次提交都有两个副本, WTF ?!” -但前提是他们确实很观察。

如果该用户以后进行了一些新的提交,然后又将其推送回主存储库,那么他们将把肮脏的历史记录推回至清理后的主存储库中,从而使您的工作无效,再次使您的历史记录变得肮脏,并创建一个非常混乱的Git历史记录您所有其他用户在下次从主要Git存储库中提取信息时都会遇到该问题。

通过计划,是否有一种方法可以让用户保留其旧存储库,但可以对其进行更新以保留已清除的历史记录?

如果可行,他们是否需要采取其他措施来减轻这些后果,作为其影响的一部分?

从技术上讲,是的。在实践中,该过程很复杂,容易出错,并且如果只有一个用户将其弄错,您将像以前一样陷入困境。

在这一点上,我们必须弄清楚为什么您要躲避此过程。是因为:

  • 您试图让用户不必了解和处理Git更改历史记录吗?听起来这可能是您的目标,因为您所说的“在我们的组织结构下,跨团队协作非常困难”,但不幸的这并不是可以实现的目标,因为Git不会让您改变历史而不会引起用户的注意。用户将不得不做某事,并且他们需要与您协调。
  • 您想减少对真正的大型存储库进行全新克隆的下载时间,希望Git仅下载更改后的Blob,而不下载所有更改的东西吗?这对于需要几个小时才能下载(寿巨大的多千兆回购稍微更合理的目标“如果你使用BFG,使回购小得多,有较少的动机) -不幸的是,由于你的Git协议的细节赢得”牛逼能够实现这些好处。Git协议旨在确定远程服务器上本地提交中未包含的提交,并发送仅包含使本地最新更新所需的定制打包文件。很好,但是请注意比较单位是提交。重写历史记录时,提交的文件树几乎没有改变-但是提交ID 改变了,因为提交ID是其父历史记录的哈希值,也是文件树的内容。Git协议仅比较提交ID,而且它们都是不同的-因此所有提交都将连同其文件树对象一起发送。该协议没有深入研究,以至于它不需要发送大多数文件树对象-因此,您没有从已经在本地存储库中拥有它们的副本的好处中获益。

坏东西在历史上有多久有关系吗?

如果您认为删除的斑点来自历史至少一年且最多三年的历史记录,此建议是否会根本改变?

如果坏东西是最近才提交的,并且还没有其他用户将其撤回(因此,在过去几个小时或几分钟内),则可以在其他任何人撤回之前快速清除主存储库上的历史记录。只要其他人提取脏数据,就需要对其进行净化处理,最简单的方法是删除并重新克隆。

如果这些坏东西是几年前犯下的,那么每个人都拥有它,需要去污染。

清理时没有推送到主存储库的杂项提交/分支怎么办?

最后,鉴于新克隆不包括任何未在上游同步的工作,您是否建议将未跟踪分支从一个克隆转移到另一个的最佳方法?

建议的解决此问题的方法是确保它不会发生。与您的团队沟通,告诉他们即将进行存储库清理,而要使其正常工作,他们要做的就是确保在开始清理之前,他们已将所有分支上的所有工作推到主存储库中。

如果有人不这样做,他们可以尝试将他们关心的分支重新建立到清除的历史记录上。对于每个feature分支,如下所示:

$ git rebase --onto clean-origin/feature unclean-origin/feature feature

...(松散地翻译为“获取功能分支上的所有提交,即在清理之前,我没有推送到主存储库,然后在该分支的主存储库已清理版本的顶部重播它们) 。

如果用户弄错了这个错误,或者忘记了只为一个分支执行此操作,那么您将回到糟糕的混合脏/干净历史记录场景。

结论

您知道您的团队,您确定他们都可以完美地执行深奥的Git重新定位操作吗?如果这样做的话,有什么好处?说到底并完成了,告诉他们删除旧的仓库并重新克隆,难道不是很容易吗?

  • 优秀的概述,以及强调社交/团队沟通方面的荣誉! (2认同)