BFG Repo Cleaner - 替代新鲜克隆

时间:2018-03-21 00:15:16

标签: git-rewrite-history bfg-repo-cleaner

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

我能够使用BFG Repo Cleaner(很棒的工具,谢谢!)将我们的.git文件夹大小减少超过1GB,就我们的存储库而言,这是一个巨大的成功。我还没有把我的裸克隆推到遥远的地方,因为我担心在理解推动然后不再重新克隆的后果之前提出这些变化。

据我所知,最佳实践表明,当历史以这种方式发生变化时,最佳解决方案是执行新的克隆。但是,我在超过2GB和23k提交的存储库中与超过50人的团队合作,在我们的结构下,跨团队协调可能非常困难。结果,我有一些问题:

  1. 如果我推动这些改变后的参考,那么后果会是什么后果,而不是创造一个新的克隆?
  2. 如果这是可行的,他们是否还需要做任何其他事情以减轻这些后果作为其拉动的一部分或者除了它们之外的其他因素?
  3. 如果您认为删除的blob来自至少一年且最多三年的历史记录,此建议是否会发生变化?
  4. 最后,鉴于新克隆不包括任何未上游同步的工作,您是否建议将未经跟踪的分支从一个克隆转移到另一个克隆?如果Git命令已经存在,我很乐意听取您的见解。
  5. 再次感谢您创建这样一个方便的工具,并希望我能完成它对我的团队项目有用。在此期间,我将继续试验我的叉子。

1 个答案:

答案 0 :(得分:4)

前言

在我们开始讨论之前,让我澄清一下在开发人员的活跃团队的背景下清理Git历史记录的建议流程(无论用于清理的技术是什么 - 是否 BFG Repo-Cleaner git filter-branch):

  1. 练习在存储库的本地一次性副本上进行几次清洁,这样您就可以确信自己可以完成并获得所需的结果,并且知道需要多长时间。
  2. 与您的团队沟通。这是必不可少的,不可避免的(因为Git专门用来抱怨并且如果历史被重写就会妨碍)以及任何团队的良好做法 :-)你需要告诉他们:
    • 为什么要清洁(例如小型回购!)
    • 计划清洁时 - 给他们适当的预先警告。
    • 要将所有的工作推送到主要仓库之前干净开始 - 它不需要合并到主分支,但所有工作需要在一个或另一个分支上推进。
    • 建议他们在清理完成后需要删除旧版本的repo,然后重新克隆新清理的存储库
  3. 当所有工作都推送到主仓库时,请执行主仓库的mirror clone。做一个这个克隆的备份,这样如果出现问题你总能回去。
  4. 运行clean(使用 BFG Repo-Cleaner 或类似git filter-branch的较慢工具),并使用git gc修剪死对象。
  5. 一旦您满意清洁已经顺利,将已清理的历史记录推回主回购(因为它是mirror克隆,所有旧分支/标记将被覆盖到新清除历史)
  6. 告诉您的团队现在是时候删除旧版本的repo,并重新克隆已清理的存储库。
  7. 那么,对你的问题:

    如果:具有回购的用户从已清理回购提取?

      

    如果我推动这些改变的裁判,后果会是什么?   人们要拉到他们现有的副本而不是创造一个   新鲜克隆?

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

    具体来说,该人的机器上发生的事情是git pull命令将旧脏历史记录和新清理历史记录合并在一起,有两个长期不同的历史记录(最初与第一个&#发散) 39;在您的历史中提交脏(在您的情况下是3年前)与一个全新且非常令人困惑的合并提交相结合。用户很少清楚这种情况发生了 - 大多数Git日志可视化工具都不会以一种可能使其显而易见的方式呈现 - 如果您很幸运,用户可能会说出类似&#34的内容;我现在已经获得了每份提交的两份副本,WTF?!" - 但前提是他们确实非常敏锐。

    如果该用户稍后进行了一些新的提交,并推回到主存储库,他们会将脏历史记录重新推送到已清理的主存储库,否定您的工作,使您的历史记录再次变脏,并创建一个非常好的混淆了Git历史记录,下次他们从主Git仓库中撤出时,你的所有其他用户都会接触到这些历史记录。

    通过规划,有没有办法让用户保留旧的仓库,但更新它以获得清理过的历史记录?

      

    他们是否需要采取其他措施来减轻这些后果   如果这是可行的,那么它们的一部分,或者除了它们之外还有什么呢?

    技术上,是的。在实践中,这个过程很复杂,容易出错,如果只有一个用户弄错了,就像以前一样搞砸了。

    此时,我们必须弄清楚你为什么要试图躲避这个程序。是因为:

    • 您试图让用户不必了解&处理改变Git的历史?听起来这可能是你的目标基于你的说法"在我们的结构下,跨团队协调会非常困难" - 但是不幸的是这不是一个可实现的目标,因为Git不会让你在没有用户注意的情况下改变历史。用户必须某事,他们需要与您协调。
    • 你想减少你真正庞大的存储库的新克隆的下载时间,希望Git只下载更改的blob,而不是所有没有的东西改变?这是一个稍微合理的目标,需要花费数小时下载巨大的数千兆字节回购(如果你使用BFG使回购更小,那么动机就会减少) ) - 不幸的是,由于Git协议的细节,你赢得能够实现这些好处。 Git协议旨在确定远程服务器上不在本地存储库中的提交,并发送一个定制的包文件,其中仅包含使本地存储库更新所需的内容。这很好,但请注意比较单位是提交。当您重写历史记录时,提交的文件树几乎没有变化 - 但提交ID 全部会发生变化,因为提交ID是它的哈希值。 父母历史记录,以及它的文件树内容。 Git协议只是比较提交ID,它们都是不同的 - 所以所有提交将被发送,连同它们的文件树对象。该协议没有深入挖掘,意识到它不需要发送大部分文件树对象 - 因此你不能从已经在本地获得它们的副本中获益回购。

    历史上糟糕的东西多久以前是否重要?

      

    如果您考虑blob,此建议是否会发生变化   被删除的是至少有一年历史的历史   大多三岁?

    如果最近发生了不好的事情,并且没有其他用户将其拉出来(因此,在最近几小时或几分钟内),您可能会在其他人拉动之前快速清理主回购中的历史记录。一旦其他人提取脏数据,就需要对其进行消毒,最简单的方法就是删除并重新克隆。

    如果多年前犯下了不好的东西,那么所有人都会拥有它,并且所有需要进行消毒。

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

      

    最后,鉴于新克隆不包括任何未同步的工作   上游,你有关于最好的结转方式的建议吗?   从一个克隆到另一个克隆的未跟踪分支?

    处理此问题的推荐方法是确保不会发生。与您的团队沟通,告诉他们将要进行存储库清理,并且他们要做的就是确保他们在开始之前将所有工作都推到主存储库的任何分支上清洁。

    如果有人不这样做,他们可以尝试将他们关心的分支机构重新定位到已清理的历史记录中。对于每个feature分支,例如:

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

    ...(松散地转换为"接受我的功能分支上的所有提交,我没有在清理之前推送到主回购,并在主要repo的该分支的清理版本之上重播它们。

    如果用户出错,或忘记只为一个分支执行此操作,您将返回错误的混合脏/清除历史记录方案。

    结论

    你了解你的团队,你确定他们都可以完美地执行深奥的Git变基操作吗?如果他们这样做有什么好处呢?毕竟说完了之后,告诉他们删除旧的仓库并重新克隆是不是更容易?