使用 Git,如何判断分支中的一个提交是否是另一个提交的后代?
这种操作依赖于在 SO 问题中详细描述的 修订的范围的概念: “ “ git 日志起源/主”与“ git 日志起源/主”的区别”。
git rev-list 应该能够从一个提交返回,直到另一个如果可达。
git rev-list
所以我会尝试:
git rev-list --boundary 85e54e2408..0815fcf18a 0815fcf18a19441c1c26fc3495c4047cf59a06b9 8a1658147a460a0230fb1990f0bc61130ab624b2 -85e54e240836e6efb46978e4a1780f0b45516b20
(边界提交以 -作为前缀)
-
如果显示的最后一次提交与 git rev-list命令中的第一次提交相同,那么它是第二次提交可以达到的提交。
如果第一次提交无法从第二次提交到达,则 git rev-list应该不返回任何内容。
git rev-list --boundary A..B
如果从 B可以到达 A,将在 A结束。 它与:
B
A
git rev-list --boundary B --not A
B是 正面引用,A是 负面参考。 它将从 B开始,然后返回到图中,直到遇到从 A可以访问的修订。 我认为,如果从 B可以直接到达 A,它将遇到(并显示,因为 --boundary选项) A本身。
--boundary
如果你想通过编程的方式检查(例如在脚本中) ,你可以检查 git merge-base A B是否等于 git rev-parse --verify A(那么从 B 可以到 A) ,或者是否是 git rev-parse --verify B(那么从 A 可以到 B)。这里需要将 git rev-parse从提交名称转换为提交 SHA-1/提交 ID。
git merge-base A B
git rev-parse --verify A
git rev-parse --verify B
git rev-parse
像在 回答中一样使用 git rev-list也是可能的。
编辑: 在现代 Git 中,这个查询以 git merge-base --is-ancestor的形式得到了明确的支持。
git merge-base --is-ancestor
如果您询问的提交之一是 枝尖,那么 git branch --contains <commit>或 git branch --merged <commit>可能是更好的非编程解决方案。
git branch --contains <commit>
git branch --merged <commit>
另一种方法是使用 git log和 grep。
git log
grep
git log --pretty=format:%H abc123 | grep def456
如果提交 def456是提交 abc123的祖先,这将产生一行输出,否则没有输出。
您通常可以省略 --pretty参数,但是如果您希望确保只搜索实际的提交散列,而不是通过日志注释等,则需要使用 --pretty参数。
--pretty
从 Git1.8.0开始,merge-base支持这个选项:
merge-base
git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>
来自手册页:
是祖先 检查第一个是否是第二个的祖先, 如果为 true,则以状态0退出,如果不为 true,则以状态1退出 由非零状态(不是1)发出的信号。
是祖先
检查第一个是否是第二个的祖先, 如果为 true,则以状态0退出,如果不为 true,则以状态1退出 由非零状态(不是1)发出的信号。
例如:
git merge-base --is-ancestor origin/master master; echo $?
基于 itub 的答案,以防您需要对存储库中的所有标记执行以下操作:
for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done
Git show-Branch Branch-sha1 commit-sha1
地点:
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'
如果您正在使用 git merge-base --is-ancestor,请确保使用 Git 2.28(Q32020)
使用 Git 2.28(Q32020) ,“ struct commit”中一些不必始终存在的字段已被移动到提交平台。
struct commit
见 提交 c752ad0,提交 c49c82a,提交4844812,提交6da43d9(2020年6月17日) by Abhishek Kumar (abhishekkumar2718)。 (由 朱尼奥 · C · 哈马诺 gitster在 犯罪合并,2020年7月6日)
abhishekkumar2718
gitster
commit-graph : 介绍 commit_graph_data_slab 签名: Abhishek Kumar
commit-graph
commit_graph_data_slab
签名: Abhishek Kumar
结构提交在许多上下文中使用。但是,成员 generation和 graph_pos仅用于提交图相关的操作,否则会浪费内存。 当我们转换到使用64位代号而不是当前的32位代号的代号 v2时,这种浪费会更加明显。 因为它们经常一起访问,所以让我们引入结构 commit_graph_data,并将它们移动到一个 commit_graph_data平台。 虽然整个测试套件的运行速度和 master一样快(系列: 26m48s,master:27m34s,快2.87%) ,但某些命令如 git merge-base --is-ancestor的运行速度比 由 Szeder Gábor 发现慢40% 。 在最小化提交-板式访问之后,速度会继续下降,但接近20% 。 Derrick Stolee 认为这种减速是由于底层算法而不是 提交板访问的缓慢性造成的,我们将在后面的系列文章中继续讨论。
结构提交在许多上下文中使用。但是,成员 generation和 graph_pos仅用于提交图相关的操作,否则会浪费内存。
generation
graph_pos
当我们转换到使用64位代号而不是当前的32位代号的代号 v2时,这种浪费会更加明显。
因为它们经常一起访问,所以让我们引入结构 commit_graph_data,并将它们移动到一个 commit_graph_data平台。
commit_graph_data
虽然整个测试套件的运行速度和 master一样快(系列: 26m48s,master:27m34s,快2.87%) ,但某些命令如 git merge-base --is-ancestor的运行速度比 由 Szeder Gábor 发现慢40% 。 在最小化提交-板式访问之后,速度会继续下降,但接近20% 。
master
Derrick Stolee 认为这种减速是由于底层算法而不是 提交板访问的缓慢性造成的,我们将在后面的系列文章中继续讨论。