使用Git,如何判断我的分支中的一个提交是否是另一个提交的后代?
答案 0 :(得分:218)
从Git 1.8.0开始,merge-base
支持此选项:
git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>
从手册页:
- 是-祖先
检查第一个是否是第二个的祖先, 如果为true,则退出状态0,否则退出状态1。错误是 由非零状态发出信号,该状态不是1.
例如:
git merge-base --is-ancestor origin/master master; echo $?
答案 1 :(得分:46)
如果你想以编程方式检查(例如在脚本中),你可以检查git merge-base A B
是否等于git rev-parse --verify A
(然后A可以从B到达),或者是{{1} (然后B可以从A到达)。此处需要git rev-parse --verify B
将提交名称转换为提交SHA-1 / commit id。
使用VonC answer中的git rev-parse
也是可能的。
如果您提出的提交之一是分支提示,那么git rev-list
或git branch --contains <commit>
可能是更好的非程序化解决方案。
答案 2 :(得分:13)
此类操作依赖于SO问题中详述的修订范围的概念:“Difference in ‘git log origin/master’ vs ‘git log origin/master..’”。
git rev-list
应该能够从提交步骤返回,直到另一个提交为止。
所以我会尝试:
git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20
(边界提交以-
为前缀)
如果显示的最后一次提交与git rev-list
命令中的第一次提交相同,那么它是从第二次提交可以提交的提交。
如果第一次提交无法从第二次提交,git rev-list
应该不返回任何内容。
git rev-list --boundary A..B
如果A
可以从A
到达,则将按B
结束
它与:
git rev-list --boundary B --not A
,B
正参考,A
否定参考。
它将从B
开始,然后返回图表,直到遇到可从A
到达的修订版。
我认为如果可以A
直接访问B
,它会遇到(并显示,因为--boundary
选项)A
本身。
答案 3 :(得分:9)
另一种方法是使用git log和grep。
git log --pretty=format:%H abc123 | grep def456
如果提交def456是commit abc123的祖先,则会生成一行输出,否则无输出。
你通常可以省略“--pretty”参数,但是如果你想确保只搜索实际的提交哈希值而不是通过日志注释等等,那么就可以了。
答案 4 :(得分:3)
https://stackoverflow.com/a/13526591/895245提到它,现在是为了让它更加人性化:
git-is-ancestor() (
if git merge-base --is-ancestor "$1" "$2"; then
echo 'ancestor'
elif git merge-base --is-ancestor "$2" "$1"; then
echo 'descendant'
else
echo 'unrelated'
fi
)
alias giia='git-is-ancestor'
答案 5 :(得分:1)
答案 6 :(得分:0)
如果您使用的是git merge-base --is-ancestor
,请确保使用Git 2.28(2020年第三季度)
在Git 2.28(2020年第三季度)中,“ struct commit
”中一些并非总是必须存在的字段已移至提交楼板。
请参见commit c752ad0的commit c49c82a,commit 4844812,commit 6da43d9,Abhishek Kumar (abhishekkumar2718
)(2020年6月17日)。
(由Junio C Hamano -- gitster
--在commit d80bea4中合并,2020年7月6日)
commit-graph
:介绍commit_graph_data_slab
签名人:Abhishek Kumar
在许多上下文中都使用struct commit。但是,成员
generation
和graph_pos
仅用于与提交图有关的操作,否则会浪费内存。当我们过渡到第v2代时,这种浪费会更加明显,该版本使用64位的代号而不是当前的32位。
由于经常将它们一起访问,让我们介绍结构
commit_graph_data
并将其移至commit_graph_data
平板上。虽然整体测试套件的运行速度与
master
一样快(系列:26m48s,master
:27m34s,速度提高了2.87%),但某些命令(例如git merge-base --is-ancestor
)却降低了40 %as discovered by Szeder Gábor。
最小化提交面板访问后,速度减慢仍然存在,但接近20%。Derrick Stolee认为,速度下降是由于底层算法而不是slowness of commit-slab access造成的,我们将在以后的系列文章中进行后续讨论。
答案 7 :(得分:-1)
建立itub的答案,以防你需要对存储库中的所有标签执行此操作:
for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done