临时分支不是多渠道构建的合理路径,因其会污染主干历史、增加合并冲突、破坏可追溯性;应改用 git worktree 隔离构建上下文,配合签名工具链在 clean 环境中注入渠道信息。

临时分支不是多渠道构建的合理路径——它会污染主干历史、增加合并冲突风险、破坏可追溯性。真正稳定的做法是用 git worktree 隔离渠道构建上下文,配合签名工具链(如 VasDolly 或 apksigner)在 clean 环境中注入渠道信息。
为什么临时分支会导致CI失败和渠道包错乱
临时分支(比如 build-channel-x)在 CI 中频繁创建/删除,容易引发以下问题:
- 分支名重复或残留:同一构建任务重试时,
git branch -D失败导致旧分支未清理,后续git checkout拿到错误状态 - 远程分支污染:
git push origin :branch-name删除失败后,远程残留分支被其他流水线误读 - Git 对象引用混乱:多个临时分支共用同一 commit hash,但渠道写入逻辑依赖工作区干净度,一旦缓存未清,
ChannelWriter可能复用上一次的渠道字段 - 无法并行:同一仓库下多个临时分支构建必须串行,否则
.git/index锁冲突直接中断构建
用 git worktree 替代临时分支的实操要点
每个渠道构建应绑定一个独立工作树,而非分支。关键动作如下:
- 在 CI 启动前,用
git worktree add --detach ../worktree-channel-x <commit-hash>创建 detached 工作树,避免任何分支指针干扰 - 渠道参数通过环境变量传入,而非修改
build.gradle或config.xml—— 这样无需 commit 任何配置变更 - 构建完成后,直接
rm -rf ../worktree-channel-x,不调用git worktree remove(CI 环境无必要维护.git/worktrees/元数据) - 务必在工作树根目录执行构建命令,否则
VasDollyPlugin读取的project.projectDir会指向主仓库,导致渠道写入位置错误
渠道信息写入阶段必须绕过 Git 跟踪
VasDolly 的 ChannelWriter 是在 APK 文件末尾追加渠道字段,这个操作本身不触碰源码。但常见错误是把渠道名硬编码进 AndroidManifest.xml 或资源文件里:
- 一旦写入 tracked 文件,就会触发 Git 状态变更,导致后续
git status非空,CI 构建脚本可能误判为“有未提交更改”而失败 - 正确做法是只让
ChannelWriter修改最终 APK 文件,所有构建中间产物(build/目录)应设为gitignore - 若需动态替换字符串(如服务器地址),用
sed -i或awk在工作树内操作,且确保目标文件不在git ls-files列表中
签名与渠道打包必须分离执行
很多团队把签名和渠道注入合在一个 Gradle Task 里,这会导致两个严重问题:
- V2/V3 签名后无法再修改 APK 字节 ——
ChannelWriter必须在签名前完成写入,否则渠道字段被丢弃 - 使用
apksigner二次签名时,若原始 APK 已含渠道字段,新签名会覆盖原有渠道信息,造成渠道丢失 - 推荐顺序:
assembleRelease→VasDollyPlugin注入渠道 →zipalign→apksigner签名。不要依赖signingConfig自动签名,手动控制流程更可靠
真正的难点不在怎么写渠道名,而在确保每次构建都从完全一致的 Git 对象出发、在完全隔离的文件系统中完成、且不留下任何 Git 状态痕迹。工作树不是“高级技巧”,它是唯一能同时满足原子性、可并行、可审计的方案。


















