如何判断一个提交是否是另一个提交的后代?

eng*_*gie 127 git

使用Git,如何判断我的分支中的一个提交是否是另一个提交的后代?

Mat*_*t R 235

从Git 1.8.0开始,支持以下选项merge-base:

git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>
Run Code Online (Sandbox Code Playgroud)

从手册页:

--is始祖

检查第一个是否是第二个的祖先,如果为true则退出状态0,否则退出状态1.错误由非零状态发出信号,该状态不为1.

例如:

git merge-base --is-ancestor origin/master master; echo $?
Run Code Online (Sandbox Code Playgroud)

  • 换句话说:`git merge-base THING --is-ancestor OF_THING &amp;&amp; echo yes || echo no` 例如:`git merge-base my-feature-branch --is-ancestor master &amp;&amp; echo yes || 回声没有` (5认同)
  • 太好了!这是一个shell脚本,它将这个答案包含在人类可重复输出的内容中:https://gist.github.com/simonwhitaker/6354592 (4认同)
  • 使用哈希时这不起作用:/ (2认同)
  • @smarber`git merge-base --is-ancestor - commit commit`用于哈希在我的身边使用`git` 2.1.4(Debian/Devuan 7.10 jessie)和1.9.1(Ubuntu 14.04可信赖)这些相当古老现在.它甚至适用于Debian wheezy,如果你做`sudo apt-get install git/wheezy-backports`. (2认同)

Jak*_*ski 47

如果要以编程方式检查(例如,在脚本中),可以检查是否git merge-base A B等于git rev-parse --verify A(然后A可以从B到达),或者是否等于git rev-parse --verify B(然后B可以从A到达). git rev-parse这里需要从提交名称转换为提交SHA-1/commit id.

git rev-listVonC中使用类似的答案也是可能的.


如果你提出的一个提交是一个分支提示,那么git merge-base --is-ancestor或者git branch --contains <commit>可能是更好的非程序化解决方案.

  • @jwg:MattR答案更好,但是这个答案(可能它被接受)比git 1.8.0和`git merge-base --is-ancestor`早2年. (6认同)
  • 两种可能的方法,它们都比@MattR答案中的一种差。 (2认同)
  • 在一个大型存储库(200万次提交)中,我比较了`git branch --contains <commit>`和`git merge-base --is-ancestor ...`的速度:3m40s vs 0.14s (2认同)

Von*_*onC 15

这种操作依赖于SO问题中详述的修订范围的概念:" git log origin/master'与'git log origin/master ...'的区别 ".

git rev-list 应该能够从提交中返回,直到另一个提交为止.

所以我会尝试:

git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20
Run Code Online (Sandbox Code Playgroud)

(边界提交以前缀为前缀-)

如果显示的最后一次提交与git rev-list命令中的第一次提交相同,那么它是可从第二次提交到达的提交.

如果第一次提交无法从第二次提交,则git rev-list不应返回任何内容.

git rev-list --boundary A..B
Run Code Online (Sandbox Code Playgroud)

将完成A,如果A可以从B.
它与:

git rev-list --boundary B --not A
Run Code Online (Sandbox Code Playgroud)

B一个正参考,和A一个负参考.
它将从B图表开始并向后走,直到遇到可从中访问的修订版A.
我认为如果A可以直接到达B,它将会遇到(并显示,因为--boundary选项)A本身.


itu*_*tub 10

另一种方法是使用git log和grep.

git log --pretty=format:%H abc123 | grep def456

如果提交def456是commit abc123的祖先,则会产生一行输出,否则不输出.

你通常可以省略"--pretty"参数,但是如果你想确保只搜索实际的提交哈希值而不是通过日志注释等等,那么它就可以了.

  • 而不是`--pretty`我使用--oneline:`git log --oneline ce2ee3d | grep ec219cc`很棒 (2认同)