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

17 浏览
0 Comments

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

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

0
0 Comments

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

从Git 1.8.0开始,可以通过merge-base选项来实现:

git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>

从man页面中可以得知:

--is-ancestor

检查第一个提交是否是第二个提交的祖先,

如果是则返回0,否则返回1。非1的非零状态表示错误。

例如:

git merge-base --is-ancestor origin/master master; echo $?

很好!下面是一个包装了上述命令并以易读的方式输出结果的shell脚本:gist.github.com/simonwhitaker/6354592

换句话说:

git merge-base THING --is-ancestor OF_THING && echo yes || echo no 例如:git merge-base my-feature-branch --is-ancestor master && echo yes || echo no

git merge-base --is-ancestor -- commit commit 在我这边使用git 2.1.4 (Debian/Devuan 7.10 jessie)和1.9.1 (Ubuntu 14.04 trusty)进行测试,这些版本都比较古老。如果你使用Debian wheezy,可以通过sudo apt-get install git/wheezy-backports安装。

为什么在没有echo yes || echo no的情况下,git bash什么都不返回?

它实际上是有返回值的,只是没有将任何内容打印到stdout。如果你熟悉C语言,这就像return 0printf("All good")之间的区别。第一个返回值是为了调用函数(可以在if语句中使用),而第二个是为了用户。因为git merge-base主要是用于脚本内部使用的,所以用户需要自己包装打印部分的代码。

0
0 Comments

如何判断一个commit是否是另一个commit的子孙?

如果你想以编程的方式进行检查(例如在脚本中),你可以检查git merge-base A B是否等于git rev-parse --verify A(则A可以通过B达到),或者是否等于git rev-parse --verify B(则B可以通过A达到)。 git rev-parse在此需要将提交名称转换为提交SHA-1 /提交ID。

使用git rev-list的方式,如VonC的回答也是一种可能的选择。

编辑:在现代Git中,可以使用git merge-base --is-ancestor来显式支持此查询。


如果你所询问的其中一个commit是一个分支尖端,那么git branch --contains <commit>git branch --merged <commit>可能是更好的非编程解决方案。

可能最快的方法是git checkout -b quickcheck <more-recent-commit-ID>,然后git branch --contains <older-commit-ID>(然后使用git branch -D quickcheck来删除临时分支)。

两种可能的方法,都比's的答案要差很多。

:MattR的答案更好,但是这个答案(可能是被接受的答案)在git 1.8.0和git merge-base --is-ancestor之前2年就存在了。

在一个大型代码库(200万个提交)中,我比较了git branch --contains <commit>git merge-base --is-ancestor ...的速度:3分40秒 vs 0.14秒

0
0 Comments

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

要解决这个问题,可以使用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是可达的。

这与git rev-list --boundary B --not A是一样的,其中B是一个正向引用,A是一个负向引用。

它会从B开始遍历图形,直到遇到一个从A可达的修订。

如果A直接从B可达,它将会遇到(并显示,因为有--boundary选项)A本身。

这似乎是一个常见的用例,我很惊讶git还没有发布一个能够完全满足这一需求的"porcelain"命令。

需要注意的是,要以编程方式检查某些内容时,不应该使用"porcelain"命令,而应该使用"plumbing"命令。

总结一下,如果第一个提交是从第二个提交可达的,那么第一个提交是第二个提交的祖先。如果不可达,则两个提交没有关联。

0