0%

repo 多分支省空间实践

ChatGPT 5 Pro 输出

适用:本地需要为同一个 manifest/远端地址准备多个分支的源码副本,并希望最大化复用磁盘空间
关键点:repo init --mirror 只是创建裸仓库镜像;真正让多个副本/分支共享对象、节省空间的,是配合 --reference 或在单一客户端用 --worktree


一、结论与选型建议

  • 仅跑 repo init --mirror 不会让现有副本自动节省空间。
  • 若要为多个分支分别准备独立工作目录(各自可单独构建):
    —— 选 方案 A:镜像 + --reference(最通用,显著省对象存储)。
  • 若只想在同一套对象库上并行检出多个分支做对比/开发:
    —— 选 方案 B:单一客户端 + --worktree(对象库完全共享,最省对象空间)。
  • 若已经有多个副本,不想重下:
    —— 用手动 alternates把它们指向镜像对象库(见“方案 C”),再 git gc 清理。

二、方案 A:镜像 + --reference(推荐)

步骤 1:创建镜像(只需一次)

mkdir -p /data/aosp-mirror && cd /data/aosp-mirror
repo init -u https://android.googlesource.com/mirror/manifest --mirror
repo sync
  • 产物是一组裸仓库(没有工作区),作为“本地源站/缓存”。

步骤 2:基于镜像初始化各分支客户端(共享对象库)

# 例如 branch1
mkdir -p ~/clients/branch1 && cd ~/clients/branch1
repo init -u /data/aosp-mirror/platform/manifest.git -b <branch1> \
--reference=/data/aosp-mirror
repo sync

# 例如 branch2
mkdir -p ~/clients/branch2 && cd ~/clients/branch2
repo init -u /data/aosp-mirror/platform/manifest.git -b <branch2> \
--reference=/data/aosp-mirror
repo sync

要点:

  • -u 指向镜像里的 platform/manifest.git(本地路径可离线);
  • --reference=/data/aosp-mirror 通过 alternates 机制共享对象,避免重复存储历史
  • 如需与镜像“脱钩”,可在 repo init 时加 --dissociate(更独立、略增空间)。

日常更新

# 更新镜像
cd /data/aosp-mirror && repo sync
# 更新客户端
cd ~/clients/branchX && repo sync

适用场景与优缺点

  • 适用:多分支、多份工作目录、可离线/内网拉取。
  • 优点:显著减少网络与磁盘;结构清晰。
  • 注意:镜像路径需稳定,构建产物(如 out/)仍各自占空间。

三、方案 B:单一客户端 + --worktree(同库多工作区)

在一个 repo 客户端里,用 Git Worktree 给部分项目全部项目添加分支工作区:

# 初始化为 worktree 模式
repo init -u <manifest-url> -b <branchA> --worktree
repo sync

# 针对大仓库举例:为 frameworks/base 再开一个分支工作区
repo forall platform/frameworks/base -c \
'git worktree add ../../worktrees/base_branchB branchB'

特点:

  • 所有 worktree 共享同一套对象库,因此对象存储几乎不膨胀;
  • 各工作区的已检出文件会各自占空间;
  • 管理稍复杂,适合“同机对比两个分支”的研发场景。

四、方案 C:已有多个副本的“就地瘦身”(手动 alternates)

不重下的前提下,让现有 checkout 共享镜像对象:

MIRROR=/data/aosp-mirror
# 为所有项目挂上 alternates(请先备份/在测试副本验证)
repo forall -c '
GITDIR=$(git rev-parse --git-dir)
mkdir -p "$GITDIR/objects/info"
echo "$MIRROR/$REPO_PROJECT.git/objects" > "$GITDIR/objects/info/alternates"
'

# 清理重复对象
repo forall -c 'git gc --prune=now'

提示:

  • 之后这些副本依赖镜像可用;如需解耦,可逐个 git repack -a -d

五、还能再省的两个开关

  • 部分克隆

    repo init --partial-clone --clone-filter=blob:none ...

    仅按需拉取大文件,降低对象与首轮同步体积。

  • 只同步需要的项目组(若 manifest 支持 groups):

    repo init -u <manifest-url> -b <branch> --groups=default,qualcomm

六、常见坑与注意事项

  1. --mirror 只在新建镜像目录时使用;不会“改造”现有客户端。
  2. 对象共享 ≠ 工作区共享:工作区(检出的源文件)与构建产物依然各自占用磁盘。
  3. 使用镜像初始化客户端时,-u 推荐用绝对路径指向 platform/manifest.git
  4. 镜像与引用路径要长期稳定;移动路径需同步修改或重新初始化。
  5. 大型工程请预估镜像磁盘(可能显著大于单一分支的源码树)。

七、速查命令清单

# A-1) 创建镜像(一次)
repo init -u https://android.googlesource.com/mirror/manifest --mirror
repo sync

# A-2) 用镜像创建不同分支的客户端(共享对象)
repo init -u /ABS/PATH/mirror/platform/manifest.git -b <branch> \
--reference=/ABS/PATH/mirror
repo sync

# B) 单一客户端 + worktree 管理多分支
repo init -u <manifest-url> -b <branchA> --worktree
repo sync
repo forall <project-path> -c 'git worktree add <dst> <branchB>'

# C) 现有副本就地共享镜像对象
repo forall -c 'echo "/ABS/PATH/mirror/$REPO_PROJECT.git/objects" > \
$(git rev-parse --git-dir)/objects/info/alternates'
repo forall -c 'git gc --prune=now'

选择建议

  • 要多份独立工作目录 → 用 镜像 + --reference
  • 要同库并行检出 → 用 --worktree
  • 已有多副本想瘦身 → 用 手动 alternates + git gc