如何判断一个提交是否是另一个提交的祖先(反之亦然)?
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>
上面的命令将向您显示可以从commit1
或commit2
访问的提交,但不能同时提交,即C1 UNION C2 – C1 INTERSECTION C2,就集合操作而言。
如果这两个提交都不是另一个的父代,那么您将看到两个子提交,但是如果其中一个是另一个的祖先,则只会看到后代提交的输出,因为祖先包含在path中的后裔,因此被排除在输出之外。
您可以从以下资源中阅读更多关于git log
和triple dot notation的信息:
- git-log(1) 。
- gitrevisions(1):指定范围 。
- 修订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'