GeneralAndroid 最小 Clone 历史清理方案

1. 目标

本方案用于回答一个明确问题:

在当前 MinIO 接入完成后,如何继续推进到“其他同事重新 clone 仓库时,尽可能接近最小下载”。

当前状态下,MinIO + 上传/下载脚本 + hook + GitLab CI 只能解决:

  • 未来新增大文件不再直接进入 Git
  • 大文件可以转由 MinIO 承接

但它不能自动清除历史里已经存在的大对象

因此,要实现“重新 clone 最小下载”,必须额外执行一次 Git 历史清理


2. 当前为什么还做不到最小 clone

当前仓库的问题分成两层:

2.1 未来污染控制

这一层已经在建设中:

  • 超过 40MB 的文件必须走 MinIO
  • 本地 hook 阻止直接提交大文件
  • GitLab CI 兜底拦截违规提交
  • 下载脚本可按 manifest 自动恢复

这一层的作用是:

  • 防止问题继续恶化

2.2 历史大对象仍然存在

这一层还没有做:

  • 历史中的 zip、webm、so、trace、pdf 等大对象仍然保留在 Git 历史里
  • 只要远端历史不清理
  • 新 clone 仍然会拉到这些旧对象

这一层决定的是:

  • 新 clone 是否真的变小

结论:

  • 当前只能做到“以后不再继续变差”
  • 不能做到“现在重新 clone 就立刻最小下载”

3. 最小 clone 的完整实现路径

必须按两个阶段来看:

阶段 A:未来治理闭环

目标:

  • 以后 >40MB 文件不再直接进入 Git

手段:

  • MinIO 上传脚本
  • MinIO 下载脚本
  • 资源 manifest
  • 本地 hook
  • GitLab CI 校验

阶段 A 完成后效果:

  • 仓库不会继续快速膨胀
  • 但历史大对象依然存在

阶段 B:历史瘦身

目标:

  • 从 Git 历史中删除已经迁移到 MinIO 的大对象

手段:

  • git filter-repo 或 BFG
  • 重写 Git 历史
  • 强推远端
  • 团队重新 clone

阶段 B 完成后效果:

  • 新 clone 显著变小
  • 拉取速度改善
  • .git 目录显著下降

只有阶段 A + 阶段 B 都完成,才能称为真正意义上的“最小 clone”。


4. 历史清理前必须满足的前提

在进入历史清理前,必须满足以下条件:

  1. MinIO 承接稳定

    • 需要迁移的大文件都已经上传到 MinIO
    • 目标桶与目录结构稳定
    • 上传/下载脚本可用
  2. manifest 可恢复

    • 每个已迁移文件都在 manifest 中有记录
    • SHA256 完整可用
    • 下载脚本可恢复这些文件
  3. 未来治理已经生效

    • 本地 hook 已安装
    • GitLab CI 已能拦截新的 >40MB 违规提交
    • 避免一边清历史,一边又继续写入新大文件
  4. 例外项已经确认

    • 例如当前明确暂不迁移:
      • main/hideapi/frida/frida-core-devkit-17.2.12-android-arm64/libfrida-core.a
    • 这些例外项是否要继续保留在 Git,需要提前决定
  5. 团队切换方式已达成一致

    • 历史重写后旧仓库不能继续无脑复用
    • 团队成员通常需要重新 clone
  6. 维护窗口已确定

    • 不应在多人频繁提交期间直接改写远端历史

5. 推荐执行顺序

5.1 冻结窗口前准备

  1. 再次导出仓库大文件报告
  2. 再次确认前 40 / 前 N 大文件的迁移状态
  3. 补齐尚未上传到 MinIO 的必要文件
  4. 确认 manifest 与下载脚本可以恢复这些文件
  5. 确认未来治理 hook / CI 已上线

5.2 备份阶段

至少做两类备份:

  1. 裸仓库备份
    • 用于完整保留清理前历史
  2. 工作区备份
    • 用于保留当前代码现场

建议至少保留:

  • 清理前仓库完整打包
  • 当前 .git 体积记录
  • 当前 git count-objects -vH 输出记录

5.3 历史重写阶段

执行思路:

  1. 确定要从历史中移除的文件列表 / 路径模式
  2. 使用 git filter-repo 或 BFG 清理历史对象
  3. 清理后执行:
    • git gc
    • git repack
  4. 检查新的仓库体积
  5. 在本地先做一轮全新 clone 验证

5.4 本地验证阶段

不能直接用旧工作区“感觉没问题”就结束,必须:

  1. 在一个全新目录重新 clone 本地清理后的仓库
  2. 记录:
    • clone 时间
    • .git 体积
    • git count-objects -vH
  3. 验证 manifest 是否还在
  4. 验证下载脚本能恢复已迁移大文件
  5. 验证 hook / CI 规则仍然成立

5.5 远端切换阶段

确认本地验证完成后:

  1. 强制推送到 GitLab
  2. 通知所有同事不要继续基于旧仓库提交
  3. 发布重新 clone 指引
  4. 统一切换到新历史

6. 历史清理后的验收标准

只有当以下条件全部满足,才算“最小 clone”改造完成:

  1. 新 clone 的 .git 体积明显小于清理前
  2. clone 不再频繁出现超时、EOF、对象传输中断
  3. 已迁移到 MinIO 的文件可通过脚本恢复
  4. 本地 hook 仍然阻止新的 >40MB 文件直接进入 Git
  5. GitLab CI 仍能兜底拦截违规提交
  6. 团队成员按新流程重新 clone 后可正常开发

7. 对其他 AI / 测试人员的要求

如果后续阶段由其他 AI 或其他测试人员接手,要求其至少完成以下动作:

7.1 清理前记录

记录以下数据:

  • du -sh .git
  • git count-objects -vH
  • clone 耗时
  • 仓库总大小

7.2 清理后验证

必须在全新目录执行,而不是继续使用旧工作区:

  1. 全新 clone 清理后的仓库
  2. 再记录:
    • du -sh .git
    • git count-objects -vH
    • clone 耗时
  3. 对比清理前后差异

7.3 功能回归

还必须验证:

  1. manifest 存在且可解析
  2. 下载脚本可恢复已迁移文件
  3. hook 拦截仍有效
  4. GitLab CI 拦截仍有效

7.4 输出报告

最终应输出一份对比报告,至少包含:

  • 清理前 .git 体积
  • 清理后 .git 体积
  • 清理前 clone 时间
  • 清理后 clone 时间
  • 恢复脚本是否成功
  • hook / CI 是否仍通过

8. 直接结论

如果只是把当前改动推到远端:

  • 只能防止未来继续恶化
  • 不能让新同事立刻最小 clone

如果要真正做到最小 clone,必须继续执行:

  1. MinIO 承接全部必要大文件
  2. 完成未来治理闭环
  3. 执行 Git 历史清理
  4. 强推远端
  5. 通知团队重新 clone

因此,“最小 clone”不是当前阶段自动获得的结果,而是 MinIO 接入之后的下一阶段专项工作