git subtree add 其他仓库后, push 一个干净的 commit log 给 gerrit 的方法
🌟 一、 场景背景与方案选择
问题场景:
- 主仓库: 存放于公网/外网(如 Gitee),主要用于文档维护。
- 子仓库(Demo): 存放于内网(如 GitLab),由各业务线独立管理。
- 核心痛点: 既要在主仓库中展示特定版本的 Demo 代码,又要解决外网无法直接
clone内网子模块(Submodule)的网络隔离问题。同时,代码审查通过 Gerrit 进行,所有提交必须附带Change-Id。
最终方案:****git subtree + --squash
- 为什么不用 Submodule? Submodule 仅记录指针,外部人员克隆主仓库时会因为连不上内网 GitLab 而拉取失败。
- Subtree 的优势: 直接将内网 Demo 的物理代码拉取并随主仓库提交,跨越网络隔离。
--squash的作用: 将子仓库杂乱的历史记录压缩成单条记录,保持主文档仓库的 Git 历史纯净。

🚀 二、 核心操作:引入子仓库代码
1. 避坑前提:千万不要手动 clone!
在使用 git subtree add 之前,绝对不能提前手动去 git clone 子仓库。subtree add 命令本身自带拉取并创建目录的功能。如果目录已存在,Git 会报错:
❌
fatal: prefix 'xxx' already exists.
2. 执行引入命令
在主仓库根目录下,分别引入两个 Demo 仓库(假设放到 thirdparty/... 路径下):
# 引入第一个 demo
git subtree add --prefix=thirdparty/skysi/use_cases/kylin-v10-digitalme-docker git@192.168.1.18:penguido/kylin-v10-digitalme-docker.git master --squash
# 引入第二个 demo
git subtree add --prefix=thirdparty/skysi/use_cases/mt-docker git@192.168.1.18:penguido/mt-docker.git master --squash
💡 原理解析: 执行完毕后,
git status会显示working tree clean。这是因为 Git 在后台已经自动为你完成了 4 次 Commit(每个子仓库产生 1 个 Squash Commit 提取代码 + 1 个 Merge Commit 合并到主分支)。
🛠️ 三、 push 一个干净的 commit log 给 gerrit
-
git reset --soft <git subtree add 前的 commit id> -
git commit -m <请输入 commit 说明> -
推送到 gerrit
git push origin HEAD:refs/for/skysi
至此,干净的 commit 进入 Gerrit 代码审查流程!✅
💣 四、 踩坑实录与急救指南
坑点 1:git rebase 由 git subtree add --squash 添加的 commit
笔者这样尝试之后遇到了复杂的合并步骤处理,涉及 merge 的 commit 等笔者不熟悉的情况,暂不推荐。
回退命令:git rebase --abort
坑点 2:git rebase 期间不小心推送到了 gerrit ,即使在 gerrit 上 abandon ,审核员的合并也会失败
解决办法:将最终需要的 commit 变基到远程 skysi 分支的最新提交上。以笔者要推送到的 skysi 分支为例
-
查看当前提交历史确认
git log --oneline -5 -
变基,将原来的父提交从"废弃的change"改为"skysi分支当前最新的正常提交"
git fetch origin skysi git rebase --onto origin/skysi HEAD~1 -
强制推送更新 Gerrit(保持同一 Change-Id,但更新父提交)
git push origin HEAD:refs/for/skysi
更多推荐


所有评论(0)