如何判断一个提交是否是另一个提交的祖先(反之亦然)?

Git是快照的DAG ,图中的每个节点代表一个提交。 每个提交可以有'n'父提交。

鉴于任何两个提交,是否有一个简单的方法来辨别这两个在DAG中的“秩序”。 git rev-list似乎是最有希望的,但我似乎无法find正确的咒语。

理想情况下,我会有如下的东西

 $ git related hash1 hash2 hash1 is ancestor of hash2 

要么

 hash2 is ancestor of hash1 

要么

 hash1 unrelated to hash2 

要么

 hash1 is equal to hash2 

使用git merge-base --is-ancestor <commit1> <commit2>

有多种方法可以find答案。 最简单的就是使用

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

git merge-base的文档:

 --is-ancestor 

检查第一个<commit>是否是第二个<commit>的祖先,如果为true,则退出状态0,否则退出状态1。 错误通过不为1的非零状态来表示。

其他选项

git log with triple dot ... notation

另一种select是使用git log并使用三点符号...来告诉Git输出子提交的集合,减去设置的交集。 基本上,它告诉你一组提交是如何相互分离的:

 $ git log --oneline --graph --left-right \ --first-parent --decorate <commit1>...<commit2> 

上面的命令将向您显示可以从commit1commit2访问的提交,但不能同时提交,即C1 UNION C2 – C1 INTERSECTION C2,就集合操作而言。

如果这两个提交都不是另一个的父代,那么您将看到两个子提交,但是如果其中一个是另一个的祖先,则只会看到后代提交的输出,因为祖先包含在path中的后裔,因此被排除在输出之外。

您可以从以下资源中阅读更多关于git log和triple dot notation的信息:

  1. git-log(1) 。
  2. gitrevisions(1):指定范围 。
  3. 修订select 。

混帐分支 – 包含选项

git-rev-list(1)似乎可以用来回答这个问题。 另一种方法是简单地将临时分支标签附加到要testing的提交上,然后对git branch使用--contains选项:

 git branch --contains <commit-to-test> 

输出将是所有包含提交树中的提交的分支,所以通过在另一个提交上使用临时分支,可以看到你正在testing的提交是否是一个祖先。

从文档:

 --contains [<commit>] 

只列出包含指定提交的分支(如果未指定,则为HEAD)。

下面的shell脚本可能会诀窍:

 if git rev-list $SHA1 | grep -q $SHA2 ; then echo "$SHA2 is ancestor of $SHA1" elif git rev-list $SHA2 | grep -q $SHA1 ; then echo "$SHA1 is ancestor of $SHA2" else echo "$SHA1 unrelated to $SHA2" ; fi 

或者,把它整齐地包装成一个git别名:

 git config --global alias.related '!function git_related() { if git rev-list $1 | grep -q $2 ; then echo "$2 is ancestor of $1" ; elif git rev-list $2 | grep -q $1 ; then echo "$1 is ancestor of $2" ; else echo "$1 unrelated to $2" ; fi } ; git_related $1 $2' 
 if (( $(git rev-list $1..$2|wc -l) == 0 )); then echo "$2 is ancestor of $1" elif (( $(git rev-list $2..$1|wc -l) == 0 )); then echo "$1 is ancestor of $2" else echo "$1 and $2 are unrelated" fi 
 git log --oneline -1 OLD_SHA..NEW_SHA 

如果这给你一些日志,那么OLD_SHA是NEW_SHA的父项。

要build立在@ helmbert的优秀的git related别名,这里是一个版本,也接受分支名称(或HEAD等)作为参数,而不是只提交id:

 git config --global alias.related '!function git_related() { commit1=`git log -n 1 --format="%h" $1` ; commit2=`git log -n 1 --format="%h" $2` ; if git rev-list $commit1 | grep -q $commit2 ; then echo "$2 is ancestor of $1" ; elif git rev-list $commit2 | grep -q $commit1 ; then echo "$1 is ancestor of $2" ; else echo "$1 unrelated to $2" ; fi } ; git_related $1 $2' 
Interesting Posts