批量检查多仓库分支同步状态需先 git fetch --all,再用 git rev-parse 和 git merge-base 对比本地与远程 commit 是否一致;超时防护、依赖版本自动校验、subtree 合并避坑及 CI 降级策略缺一不可。

如何用脚本批量检查多个仓库的分支同步状态
直接跑脚本比一个个 git fetch && git status 省 80% 时间。关键不是“能不能查”,而是查完之后能立刻判断哪些仓库落后、哪些已合并、哪些有冲突风险。
核心思路:进每个仓库目录,执行 git rev-parse origin/main 和 git rev-parse HEAD 对比,再结合 git merge-base 判断是否已包含远程变更。
- 必须先
git fetch --all,否则本地origin/main是过期的 - 避免用
git diff origin/main...HEAD——它只比较差异,不反映是否已 merge 过该 commit - 推荐用
git merge-base origin/main HEAD输出和git rev-parse origin/main是否一致来判定“是否已同步” - 脚本中加
timeout 10s防止某个仓库卡死(比如网络异常或大 LFS 文件阻塞)
合并前自动校验依赖仓库版本一致性
多仓库协作时,A 项目依赖 B 项目的某个 tag 或 commit,但 B 仓库的 main 已更新,A 却没同步——这种“隐性不一致”是线上故障常见源头。
不能只靠人肉核对 package.json 或 go.mod 里的版本号,得让脚本主动验证。
- 在 A 仓库根目录读取依赖声明(如
require github.com/org/b v1.2.0),提取仓库路径和版本标识 - 自动 clone 或
git -C /path/to/b rev-parse v1.2.0检查该 tag 是否存在且非空 - 若版本是 commit hash,需确认该 hash 在 B 的
main分支历史中(git -C /path/to/b merge-base --is-ancestor <hash> main) - 失败时输出明确提示:“
b@v1.2.0不存在,当前b/main最新 commit 是abc1234”
用 git subtree 合并时绕过重复提交检测
当多个子仓库都往统一 mono-repo 的不同子目录 push,再用 git subtree add 时,常因“相同 commit 已存在”报错,尤其在 CI 中反复触发。
这不是 bug,是 git subtree 默认行为:它会检查目标 commit 是否已在当前 repo 历史中出现过,防止重复引入。
- 加
--squash参数可跳过该检查,但会丢弃原 commit 历史——仅适合不关心子仓库完整历史的场景 - 真正保留历史又避免报错,要用
git subtree add --prefix=xxx remote/branch --no-commit+ 手动git commit,绕过 subtree 内部的重复校验逻辑 - 更稳妥的做法:提前用
git filter-repo --mailmap统一作者邮箱,避免因作者信息微小差异被识别为“不同 commit” - 注意
git subtree pull不支持--squash,升级到git-filter-repo替代才是长期解法
CI 中合并进度脚本的超时与降级策略
把多仓库合并检查放进 CI,最容易踩的坑是“一个仓库慢,整个流水线卡住”。真实环境里,网络抖动、私有 Git 服务响应延迟、大文件拉取失败都很常见。
- 每个仓库操作必须设硬性超时,例如
timeout 30s bash -c 'cd $repo_dir && git fetch --depth=1 origin main 2>&1' - 失败时不立即 fail 整个 job,而是记录 warning 日志,并标记该仓库为 “skipped_for_timeout”
- 允许配置白名单:对核心仓库(如 infra、auth)要求严格失败,对边缘文档类仓库允许跳过
- 最终输出汇总报告时,用颜色区分状态:
✅ synced、⚠️ timeout、❌ missing commit,别只扔 exit code
真正难的不是写脚本,而是定义清楚“同步完成”的边界:是远程分支指针一致?还是所有依赖 commit 都已 merge 进主干?后者需要遍历 merge commit 的 parent,容易漏掉 squash merge 场景——这点常被忽略。


















