如何删除不再位于HEAD中的旧/历史Git对象?

bihw5rsg  于 2023-09-29  发布在  Git
关注(0)|答案(1)|浏览(102)
  • 我有一个Git仓库,有近30万个提交,超过20年。这个仓库是从SVN迁移到Git的结果,所以我可以自由地重写历史。它只有一个分支,没有标签。*
  • 通常情况下,文件在提交时被添加,然后在稍后被删除,在存储库中留下我不想保留的对象。*
    如何无条件删除HEAD中不再存在的所有对象?

我尝试过的事情:

  • BFGgit filter-branch似乎都没有涵盖这个用例(如果我不编写一个检索所有旧对象ID的脚本)。
  • Git存储库正在使用KDE的svn2git进行迁移(* 在CI中重复,直到我对结果满意 *),但它的规则似乎也不涵盖这种用例。

我不知道git-filter-repo是否可以做到这一点。
编辑:

  • 澄清:我的最终目标是减少存储库的大小,同时仍然保持最大量的历史记录。多年来,许多文件(二进制文件太多-小的和大的)被提交,后来被删除。大型存储库会导致克隆缓慢、Git CLI缓慢以及其他工具(例如CI).*
ykejflvf

ykejflvf1#

就我个人而言,我会使用BFG来完成这类任务(我是BFG的作者,所以这并不奇怪!)),虽然它的行为方式可能并不理想,因为你要求的是-你说“删除所有不再在HEAD中的对象”,从技术上讲,这个命令将做到这一点:

bfg --delete-files "*"

.它说“delete any file”,但是因为BFG保护你的HEAD提交,你的HEAD提交将保持不变,它的所有文件都完好无损。
然而,也许是不希望的,这个特定的--delete-files参数的实现 * 将 * 从早期提交中删除这些文件,所以结果是几乎所有以前的提交都会删除所有文件-你可以看到这里的HEAD提交-所有文件都保留了the original commit,但它们似乎都是突然引入的最新提交:
https://github.com/bfg-repo-cleaner-demos/rails-with-all-non-head-files-deleted/commit/b689725edf03b86c31dc3e8d589fd01c0435ec8c
BFG的另一种方法是使用--strip-blobs-with-ids参数,这个参数要具体得多,但正如您已经注意到的,您可能需要编写一个脚本来找出每个不在HEAD提交中的文件的blob id。
我鼓励你问问自己,你希望这个清理操作的 * 回报 * 是什么-也就是说,我知道你说过你想无条件地删除所有不再在HEAD中的对象-但是你想从中获得什么回报呢?以下是一些可能的奖励:

  • 减少了存储库的整体数据大小,使其克隆速度更快,并在托管和开发人员笔记本电脑上占用更少的存储空间
  • 删除过去可能已提交到存储库的任何可能的敏感数据-如果您所拥有的都是历史上任何地方的HEAD的最新文件,那么不需要的凭据或个人数据就没有可能隐藏在那里。

如果其中的第一个-减少数据大小-是您的主要关注点,那么可能值得检查与仅删除大文件相比,从历史记录中删除 * 所有 * 文件可以获得多少额外好处。由于the data structures used by git,它非常擅长处理存在于数千次提交中的小文件--它们最终可能不会占用大量的存储空间--只有大文件才会导致严重的膨胀。
因此,我建议您在repo的测试副本上运行上面的bfg --delete-files "*"命令,并检查结果的大小减少了多少-例如,可能是90%。这将是最大可能的规模节省。然后,您可以在测试存储库的新副本上执行不同的运行,在其中尝试以下命令:

bfg --strip-blobs-bigger-than 1M

这只是删除“大”文件-大小超过1 MB的文件。最终的回购规模是多少?也许在这种情况下,大小缩减仅为85%-但是您的大部分历史都完好无损,这可能是有用的,并且额外的5%空间节省可能不值得进一步追求。

相关问题