GeneralAndroid 大文件迁移方案(GitLab → MinIO)
1. 背景与目标
当前 GeneralAndroid 仓库已经出现明显的大文件污染问题,主要表现为:
- 仓库工作区总大小约 31.10 GiB
.git目录大小约 15.43 GiB- Git 跟踪文件总大小约 12.87 GiB
- Git 跟踪前 40 大文件合计约 8.43 GiB,占跟踪文件总体积 65.51%
这说明仓库不仅当前文件体积偏大,而且 Git 历史对象中已经累积了大量超大二进制文件。这会直接带来:
git clone/git pull容易超时、中断、EOF- 仓库同步速度明显下降
- GitLab 服务端传输对象负担过重
- 本地
.git持续膨胀,维护成本越来越高
本方案的目标是:
- 将大文件从 Git 仓库中迁移到已部署的 MinIO
- 让 Git 仓库回归“源码仓库”定位
- 建立大文件后续托管规范,防止再次污染
- 在条件成熟后,清理 Git 历史中的大对象,根治 clone/pull 问题
2. 总体方案
已确定采用以下职责划分:
- GitLab:仅存放源码、脚本、文档、配置、少量必要小样本
- MinIO:存放大文件资源,包括发布包、视频、trace、书籍、工具二进制
- 仓库内清单文件:记录 MinIO 上的资源位置、校验值、用途说明、下载方式
同时约定:
assets/resource_manifest.json是权威数据源assets/resource_manifest.md与assets/assets_sha256.txt都由脚本根据 JSON manifest 派生生成,不作为手工维护入口- 上传脚本只有在
mc stat确认远端对象存在且 size 符合预期后,才允许写 manifest / SHA / history
2.2 远程 clone 与恢复主路线
当前主路线已经明确为:
- 远程 clone / 资产恢复优先走公网
mcendpoint:http://tx2.898311.xyz:9010 - 通过环境变量
GENERALANDROID_MC_ALIAS、GENERALANDROID_MC_ENDPOINT、GENERALANDROID_MC_ACCESS_KEY、GENERALANDROID_MC_SECRET_KEY让scripts/bootstrap_repo.sh自动创建 alias scripts/download_assets.py/scripts/upload_assets.py保持兼容现有localalias,本机工作流不移除- 预签名下载保留为后续增强路线,不作为当前主流程前置条件
这意味着阶段二的长期管理方式,已经从“手工预配 local alias”调整为“公网 mc + 受限账号 + bootstrap 自动配置”。
generalandroid/releases/media/traces/tools/books/
分类规则:
releases/:zip、tar.gz、7z、apk、完整发布包、离线分发包media/:webm、mp4 等录屏/培训/分享视频traces/:atrace、perfetto、hprof、bugreport 等分析数据tools/:so、a、jar、独立工具二进制、工具链文件books/:pdf、电子书、参考资料
3. 迁移原则
3.1 必须迁移的对象
以下类型默认不应继续留在 Git 主仓库中:
.zip.tar.gz.7z.webm.mp4.pdf.hprof.atrace.perfetto-trace- 超大
.so.a.jar - 编译产物
- 第三方工具二进制
- 可通过脚本重新下载或生成的大样本文件
3.2 可保留在 Git 中的对象
仅保留以下内容:
- 源码
- 配置文件
- 文档
- 小型示例文件
- 必须纳入版本控制且体积很小的测试样本
- 经明确确认、当前阶段暂不迁移的少数大文件
当前已确认的例外:
- 当前无例外项,原先暂不迁移的
main/hideapi/frida/frida-core-devkit-17.2.12-android-arm64/libfrida-core.a已改为正式迁移,并已上传到 MinIO。
3.3 仓库中不再保留本体,只保留索引
迁移后,仓库中保留:
- 资源清单(manifest)
- SHA256 校验信息
- 下载脚本
- 上传脚本(可选)
- 资源使用说明
不再保留大文件本体。
4. 分阶段实施方案
阶段一:止血(立即执行)
目标:停止继续向 Git 提交大文件。
动作:
- 根据当前大文件报告,识别需迁移文件
- 将这些文件上传到 MinIO
- 在仓库中建立资源清单
- 从 Git 当前版本中删除这些大文件
- 补充
.gitignore规则,防止再次提交
阶段一效果:
- 后续提交不再继续恶化
- Git 当前分支体积增长被控制
- 开发流程恢复可维护状态
注意:
- 阶段一 不能缩小已有 Git 历史体积
- 只能阻止问题继续扩大
阶段二:规范化(紧随阶段一)
目标:建立长期可维护的大文件管理方式。
动作:
- 固化 MinIO 目录规范
- 固化仓库资源清单格式
- 增加下载脚本
- 视需要增加上传脚本
- 在团队内约定:大资源一律不直接进 Git
阶段二效果:
- 仓库和大资源彻底解耦
- 新资源都有固定归档位置
- 后续维护成本大幅下降
阶段三:历史治理(择机执行)
目标:真正缩小 Git 仓库体积,根治 clone/pull 问题,让后续新同事重新 clone 时尽可能接近“最小下载”。
动作:
- 完成未来治理闭环(即 >40MB 文件全部走 MinIO,禁止继续把新大文件写入 Git)
- 根据迁移映射清单和 MinIO manifest,确认历史中要剔除的大文件都已有可恢复落点
- 对当前仓库做完整备份(裸仓库备份 + 工作区备份)
- 使用
git filter-repo或 BFG 清理历史大文件 - 本地执行
git gc/git repack,验证瘦身结果 - 在维护窗口强制推送到 GitLab
- 所有使用者重新 clone 或按新方式同步
- 用全新 clone 做一次最小下载验证
阶段三效果:
.git体积显著下降- clone / pull 恢复正常
- GitLab 服务端传输负担下降
- 新同事重新 clone 时,不再被旧历史大对象拖累
注意:
- 该阶段属于高风险操作
- 会改写提交历史
- 必须在确认窗口期、完成备份、确认使用者同步策略后执行
- 只有阶段三完成后,重新 clone 才能真正接近最小下载
4.3.1 阶段三的实施前提
在历史清理开始前,必须满足以下前提:
- MinIO 上传 / 下载 / manifest / hook / GitLab CI 流程已经稳定
- 需要保留的大文件已经迁移到 MinIO,且可通过脚本恢复
- 暂不迁移例外项已经单独确认(当前例外:
main/hideapi/frida/frida-core-devkit-17.2.12-android-arm64/libfrida-core.a) - 团队已经接受“重写历史后需要重新 clone”的切换方式
- 已确定维护窗口,避免在活跃开发期直接改写远端历史
4.3.2 阶段三的推荐执行顺序
建议严格按以下顺序执行:
- 冻结新增大文件提交
- 再次导出仓库大文件清单,确认要剔除的对象集合
- 核对 MinIO manifest,确保对应对象可恢复
- 创建本地裸仓库备份
- 创建工作区备份
- 使用
git filter-repo/ BFG 清理历史 - 本地重新统计:
git count-objects -vHdu -sh .git
- 用全新临时目录重新 clone 本地清理后的仓库,验证:
- clone 时间
.git体积- 下载脚本恢复能力
- 确认无误后再推送远端
- 发布团队切换说明,要求全员重新 clone
4.3.3 历史清理完成后的验收标准
只有以下全部满足,才算“最小 clone 改造完成”:
- 新 clone 的仓库
.git体积明显低于当前状态 - clone 过程中不再因为历史大对象频繁超时/EOF
- 已迁移文件可从 MinIO 恢复
- 本地 hook 和 GitLab CI 仍能阻止新的 >40MB 文件直接进入 Git
- 团队成员按照新流程重新 clone 后可正常开发
4.3.4 对其他 AI / 测试人员的要求
如果后续由其他 AI 或其他人员负责阶段三验证,应要求其至少完成以下检查:
- 记录历史清理前后的:
du -sh .gitgit count-objects -vH- clone 耗时
- 在一个全新目录执行 clone,不能直接复用旧工作区
- clone 后立刻验证:
- manifest 是否存在
- 下载脚本是否可恢复已迁移资源
- 验证一个违规 >40MB 文件提交仍会被 hook / CI 拦截
- 输出一份“历史清理前后对比报告”
5. 迁移对象分类规则
后续生成详细迁移清单时,按照以下规则归类:
5.1 releases/
适用于:
tool_new.zip- 各类发布包
- 归档安装包
render_doc_hook.zip- 其他 zip/tar.gz/7z 成品包
5.2 media/
适用于:
.webm.mp4- 录屏、课程、分享视频
5.3 traces/
适用于:
.atrace.hprof- bugreport
- perfetto 数据
- 分析样本
5.4 tools/
适用于:
.so.a- 大型
.jar - 独立二进制工具
- 第三方工具链
5.5 books/
适用于:
.pdf- 电子书
- 技术资料附件
6. 建议的仓库改造内容
6.1 建议新增的清单文件与脚本
建议在仓库中新增以下文件:
assets/resource_manifest.json(主清单)assets/resource_manifest.md(阅读视图,由 JSON 派生)assets/assets_sha256.txt(派生校验文件)assets/asset_history.jsonl(生命周期操作历史)scripts/upload_assets.pyscripts/batch_upload_assets.pyscripts/download_assets.pyscripts/list_assets.pyscripts/update_asset.pyscripts/remove_asset.pyscripts/bootstrap_repo.shscripts/install_git_hooks.sh.claude/commands/clone-init.md
6.2 清单文件职责
当前文件职责必须明确区分:
assets/resource_manifest.json- 主清单
- 唯一权威数据源
- 上传 / 下载 / 查询 / 更新 / 删除 / 校验脚本都以它为准
assets/resource_manifest.md- 阅读视图
- 由 JSON 自动派生
- 不手工维护
assets/assets_sha256.txt- 派生校验文件
- 由 JSON 自动派生
- 不手工维护
assets/asset_history.jsonl- 生命周期历史记录
- 只追加,不回写旧记录
因此当前不应再把 resource_manifest.md 视为主清单。
6.3 下载脚本职责
下载脚本负责:
- 按资源清单下载所需文件
- 校验 SHA256
- 放回约定本地路径
- 支持按分类下载,例如:
--media--tools--traces--all
- 支持
--jobs并发下载 - 支持
--continue-on-error,单文件失败时继续处理剩余任务 - 支持 resumable rerun:已存在且 size + SHA256 校验通过的本地文件直接跳过
- 下载前先对远端对象执行
mc stat --json,至少确认对象存在且 size 与 manifest 一致
6.4 .gitignore 建议方向
后续应把明显的大文件类型或产物目录加入 .gitignore,例如:
- 打包产物目录
- trace 输出目录
- hprof 输出目录
- 大型 zip/tar.gz/7z 产物目录
- 工具构建输出目录
注意:
.gitignore不能解决历史污染- 只能阻止后续重复提交
7. 执行顺序建议
建议采用以下顺序:
- 固化 MinIO 目录规范(已确定)
- 根据前 40 大文件生成详细迁移清单
- 逐批上传到 MinIO
- 生成并补充仓库资源清单与校验文件
- 删除 Git 当前版本中的大文件并补
.gitignore - 验证本地脚本可以按需拉取资源
- 对批量迁移场景优先使用并发上传脚本:worker 只负责
mc cp+mc stat确认,manifest / SHA / history 统一由主线程串行落盘 - 选择维护窗口执行历史清理
不建议的顺序:
- 先做历史重写,再决定资源怎么放
- 先删仓库大文件,但没有清单和下载入口
- 没有备份就直接改写历史
8. 风险与注意事项
8.1 当前版本删除 ≠ 历史清理
从当前分支删掉大文件,只会减少后续维护压力,不会自动缩小 .git 历史。
8.2 历史重写影响所有使用者
一旦用 git filter-repo / BFG 清历史:
- 所有人本地分支都可能需要重新同步
- 旧 commit hash 会变化
- 需要明确切换窗口
8.3 迁移前必须保证资源可追溯
迁移后不能出现:
- 只知道文件迁走了,不知道放哪
- 没有 SHA256
- 没有下载脚本
- 文档引用失效
8.4 MinIO 权限要先想清楚
至少要明确:
- 是仅局域网访问还是公网访问
- 是否允许匿名下载
- 是否只允许登录后访问
- 文档中记录的链接是否长期有效
9. 推荐最终状态
理想完成态如下:
Git 仓库中
只保留:
- 源码
- 文档
- 配置
- 少量小样本
- 资源清单
- 下载脚本
MinIO 中
统一托管:
- 大型发布包
- 视频资料
- trace / hprof / bugreport
- 大型工具链文件
- PDF / 书籍资料
Git 历史
经过清理后:
- 不再包含超大 zip、视频、trace、工具包等历史对象
- clone/pull 大幅恢复正常
11. 大文件资源的长期维护方式
后续大文件不再按“Git 直接版本化文件本体”的方式维护,而采用:
- Git:维护资源索引和元数据
- MinIO:维护资源文件本体
11.1 增删改查原则
新增(增)
新增大文件时:
- 执行上传脚本
- 上传文件到 MinIO
- 自动更新 manifest / sha256
- 提交元数据文件,不提交大文件本体
删除(删)
删除大文件时必须同时处理:
- Git 中的 manifest 条目
- MinIO 中的对象
禁止只删一边。
修改(改)
修改大文件时,不建议原地覆盖,而应:
- 上传新对象
- 更新 manifest 指向
- 更新 sha256 / size / uploaded_at
- 提交 manifest 变更
查询(查)
查询需要分别从两层进行:
- Git 层:
resource_manifest.jsonresource_manifest.md- Git 提交历史
- MinIO 层:
mc lsmc stat
11.2 增删改查脚本落地情况
当前已实现:
scripts/upload_assets.py:新增并登记大文件scripts/download_assets.py:从 MinIO 恢复已登记资源scripts/list_assets.py:列出 / 查询当前已登记资源scripts/update_asset.py:更新已登记资源的新版本scripts/remove_asset.py:删除 manifest 条目并删除或保留 MinIO 对象
同时已引入资产历史记录:
assets/asset_history.jsonl
作用:
- 记录 upload / update / remove 操作
- 用 Git 保留操作历史
- 支撑单文件生命周期追踪和问题排查
建议统一通过这些脚本维护大文件,不要手工改 manifest,也不要手工直接删 MinIO 对象后忘记同步 Git 元数据。
11.3 远程同事 / 非局域网环境说明
当前脚本默认调用 mc alias local,这只是一个默认约定,不代表只能在局域网环境下使用。
只要使用者机器上的 mc alias 指向一个其网络可访问的 MinIO/S3 兼容入口,脚本就能继续工作。
这意味着:
- 局域网同事可以使用本地 / 内网 MinIO 入口
- 非局域网同事如果能访问公网 MinIO 域名,也可以工作
- 如果飞出局域网后无法访问目标 MinIO 地址,则上传/下载脚本无法正常使用
因此,对远程同事真正的约束不是脚本本身,而是:
- MinIO 服务是否可达
mcalias 是否已正确配置- 账号凭证是否可用
- 网络速度是否可接受
后续如需更好支持远程同事,可继续增强:
- 支持通过环境变量配置默认 alias
- bootstrap 增加 alias 选择能力
- 文档中拆分内网 / 外网初始化说明
11.4 下一阶段实施内容
当前状态下,“TOP40 范围内对象迁移到 MinIO”已经完成,下一阶段重点不再是继续补迁,而是:
- 分批从当前仓库版本中删除已迁移大文件本体
- 持续验证 bootstrap / 下载脚本恢复链路
- 继续验证远程同事 / 外网 MinIO API 访问方式
- 准备历史清理执行清单与维护窗口
完成后即可形成完整的“增删改查 + MinIO 同步维护 + 当前版本瘦身 + 历史清理准备”闭环。