【问题标题】:Remove spam from git history从 git 历史记录中删除垃圾邮件
【发布时间】:2019-12-20 01:10:22
【问题描述】:

我“继承”了一个肮脏的 git 存储库,其中包含大约 5k 次有效提交和大约 50k 次垃圾邮件提交(这是曾经是世界可写 wiki 的编辑历史)。我们正在迁移格式,所以这是改写历史的好时机。我不想完全放弃历史,但无论是提交量还是原始内容量,垃圾邮件都是压倒性的。回滚到最后一个好的提交的旧的审核技术留下了很多垃圾。

使用git log -S 和一些正则表达式工作,我可以轻松找到大约 80% 的错误提交。大多数垃圾邮件内容非常明显。问题是我不确定如何处理我想要删除的大量提交。

请注意,我对 git 非常熟悉,并且每小时使用一次 git rebase(除非git revise 承担了很多负载,否则我会一直使用它),而且我知道如何手动完成此操作,但我需要一个自动化的解决方案。通常我会求助于git filter-branch,但我不确定使用什么工具来检查当前差异。

我曾考虑编写一个脚本来操作变基脚本,但我认为这会给我带来误报的麻烦。我可能可以捕获并丢弃原始的破坏和回滚,但是当我错过了该等式的一侧时会发生什么?我希望可能匹配的 REST 在其中一个没有干净地变基时成功而不是失败。

注意我不想根据我的匹配操作文件的内容或添加/删除文件,我想检查 patch 的内容并决定根据它选择或删除.

最好的git 工具是什么?

【问题讨论】:

  • “垃圾邮件提交”是什么意思?我是否正确假设“回滚到最后一个好的提交”确实意味着分支已重置,而是在留下损坏的提交和重置的事实之后添加了恢复提交作为线性历史中的单独提交?在这种情况下,您可能会尝试搜索具有相同树哈希的提交并忽略这些提交之间的所有历史记录。
  • git 仓库是公开的吗?能够看到实际的历史可能有助于我们制定答案......
  • @cmaster 不,不幸的是,“还原”是我手动从 wiki 页面删除垃圾并保存(因此产生新的提交)。结果类似于还原提交,但几乎不完全相同。还原通常是手动发生的,而垃圾邮件是自动发生的,因此有 10 个小型垃圾邮件提交(例如,每个添加约 10 个链接)然后是大回滚提交(删除约 100 个链接)。
  • @larsks 不幸的是,它现在不公开。它最终会朝着那个方向发展,但有一些私人的东西需要首先编辑。不过,我几乎无法解决所有垃圾邮件的问题。
  • git filter-branch 有帮助吗?

标签: git rebase spam git-filter-branch


【解决方案1】:

一种可能性是使用Git 的graftfile 或git replace。首先,识别所有“好的”提交,即非垃圾邮件提交,还包括“清理/恢复”提交。例如,通过提交者电子邮件或类似机制过滤您的历史记录(您提到了 pickaxe/-S)。

一旦获得“良好”提交列表,使用paste 命令进行简单转换即可获得移植文件的内容,即:

commit parent1 parent2 parent3...

说,你好的提交如下(最新的提交在上面):

b3fb1155cd5352da674d93ce4b0a1567674f6d27
b460ef0aea564e587e5866107c0fc52adf552ca1
9f803dd18c89e13f47170e1ace1d0abb992cfeee

那么您需要在您的移植文件中包含以下内容:

b3fb1155cd5352da674d93ce4b0a1567674f6d27 b460ef0aea564e587e5866107c0fc52adf552ca1
b460ef0aea564e587e5866107c0fc52adf552ca1 9f803dd18c89e13f47170e1ace1d0abb992cfeee

这很容易通过以下方式获得:

sed 1d commits | paste commits - | sed '$d'

将此文件移动到.git/info/grafts 并使用git loggitk 验证生成的历史记录。如果您对结果感到满意,请使用git filter-branch 重写历史记录并保存您的移植文件。然后您可以删除.git/info/grafts

请参阅https://stackoverflow.com/a/3811217/112968 了解如何使用非弃用替换机制。在这种情况下使用移植文件更容易解释(并且它仍然适用于当前的 Git 版本,所以为什么不使用它?:))

【讨论】:

    【解决方案2】:

    一种可能的解决方案,涉及git rebase

    您提到您能够确定要删除哪些提交,并且 rebase 期望选择(甚至删除)提交列表。但是你不能简单地删除,因为那样你的“恢复”提交也需要被删除(它们可能包含不相关的更改?)。

    考虑以下变基脚本:

    pick A normal edit
    pick B spam
    pick C spam
    pick D spam
    pick E spam
    pick F revert spam
    pick G normal edit
    

    我假设您想“删除”所有垃圾邮件和还原提交的更改。这可以通过以下变基脚本来实现:

    pick A normal edit
    fixup B spam
    fixup C spam
    fixup D spam
    fixup E spam
    fixup F revert spam
    pick G normal edit
    

    如果您有要“删除”的提交列表(包括“恢复”提交),您应该能够通过 sed 或类似工具将所有匹配行替换为 fixup 而不是pick.

    如果你能通过提交主题来识别错误提交,那就更容易了。

    【讨论】:

      猜你喜欢
      • 2014-06-19
      • 2020-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-30
      相关资源
      最近更新 更多