如何查找引入特定submodule commit的Git主仓库提交
子模块变更溯源:定位子模块提交首次进入主仓库的时机
问题场景
主仓库FOO包含子模块BAR,两者提交历史如下:
子模块BAR提交历史(最新提交在前) o - commit E | o - commit D | o - commit C | o - commit B | o - commit A 主仓库FOO中子模块更新历史(最新提交在前) o - commit 3: 更新子模块至commit E | o - commit 2: 更新子模块至commit C | o - commit 1: 更新子模块至commit A
需要确定子模块BAR的commit B首次被纳入主仓库FOO的提交,预期结果为commit 2——因为commit 1的子模块指向A(不含B的变更),commit 2指向C(已包含B的所有变更)。
当前临时方案
- 进入主仓库FOO,提取子模块BAR的更新记录:
cd foo git log -p bar
手动记录各主仓库提交对应的BAR哈希(如commit 1对应A、commit 2对应C、commit 3对应E)。
2. 进入子模块BAR,找到commit B的哈希:
cd bar git log
- 手动比对BAR的提交顺序,判断B在A之后、C之前,从而得出
commit 2是引入B变更的主仓库提交。
注:git submodule summary仅报告子模块合并的起止哈希,无法直接满足需求。
优化解决方案
可以通过组合Git命令直接定位目标主仓库提交,无需手动比对:
单命令快速检索
cd foo git log --oneline --grep="$(git -C bar rev-parse B)" --follow -- bar
精准定位脚本命令
如果需要更精准地输出第一个符合条件的主仓库提交,可使用以下脚本:
cd foo # 获取子模块BAR中commit B的哈希值 bar_b_hash=$(git -C bar rev-parse B) # 遍历主仓库中所有修改子模块BAR的提交,找到首个包含B变更的提交 git log --oneline --follow -- bar | while read commit_info; do commit_hash=$(echo "$commit_info" | cut -d' ' -f1) # 获取当前主仓库提交指向的BAR哈希 bar_target_hash=$(git show "$commit_hash":bar) # 检查B是否是BAR目标版本的祖先(即该版本已包含B的变更) if git -C bar merge-base --is-ancestor "$bar_b_hash" "$bar_target_hash"; then echo "$commit_info" break fi done
该命令逻辑:
- 遍历主仓库FOO中所有修改子模块BAR的提交
- 对每个提交,提取当时指向的BAR版本哈希
- 通过
merge-base --is-ancestor检查commit B是否已包含在该BAR版本中 - 找到第一个满足条件的主仓库提交后立即输出并终止执行
内容的提问来源于stack exchange,提问作者MrMas
相关产品推荐
相关产品推荐

