75

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

给定任何两个提交,是否有一种简洁的方式来辨别 DAG 中这两个提交的“顺序”。 git rev-list似乎是最有希望的,但我似乎找不到正确的咒语。

理想情况下,我会有以下内容

$ git related hash1 hash2
hash1 is ancestor of hash2

或者

hash2 is ancestor of hash1

或者

hash1 unrelated to hash2

或者

hash1 is equal to hash2
4

5 回答 5

96

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

找到答案的方法不止一种。最简单的就是使用

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

从文档中git merge-base

--is-ancestor

检查第一个<commit>是否是第二个的祖先,<commit>如果为真则以状态 0 退出,否则以状态 1 退出。错误由非 1 的非零状态发出信号。

其他选项

带有三点...符号的 git log

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

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

上述命令将向您显示可从commit1或访问的提交commit2,但不能同时访问,即 C1 UNION C2 - C1 INTERSECTION C2,就设置操作而言。

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

您可以git log从以下资源中了解更多关于三点符号的信息:

  1. 混帐日志(1)
  2. gitrevisions(1):指定范围
  3. 修订选择

git branch --contains 选项

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

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

输出将是在其提交树中某处包含提交的所有分支,因此通过在另一个提交上使用临时分支,您可以查看您正在测试的提交是否是祖先。

从文档中:

--contains [<commit>]

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

于 2013-08-20T21:29:39.607 回答
11

以下 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'
于 2013-08-20T21:36:09.817 回答
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
于 2013-08-20T21:38:45.710 回答
0
git log  --oneline -1  OLD_SHA..NEW_SHA

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

于 2016-06-20T16:24:55.433 回答
0

为了构建 @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'
于 2017-10-12T15:46:44.440 回答