Git是DAG个快照,图中的每个节点都代表一个提交。每个提交都可以有'n'个父提交。
鉴于任何两次提交,是否有一种简洁的方法来识别DAG中这两者的“顺序”。 git rev-list
似乎是最有希望的,但我似乎无法找到正确的咒语。
理想情况下,我会有以下内容
$ git related hash1 hash2
hash1 is ancestor of hash2
OR
hash2 is ancestor of hash1
OR
hash1 unrelated to hash2
OR
hash1 is equal to hash2
答案 0 :(得分:59)
git merge-base --is-ancestor <commit1> <commit2>
找到答案的方法不止一种。最简单的是使用
git merge-base --is-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
和三点符号的更多信息:
git-rev-list(1)似乎可以用它来回答这个问题。另一种方法是简单地将临时分支标签附加到您要测试的提交,然后使用git branch
的--contains
选项:
git branch --contains <commit-to-test>
输出将是在其提交树中某处包含提交的所有分支,因此通过在另一个提交上使用临时分支,您可以查看您正在测试的提交是否是祖先。
来自文档:
--contains [<commit>]
仅列出包含指定提交的分支(如果未指定,则为HEAD)。
答案 1 :(得分:7)
以下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'
答案 2 :(得分: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
答案 3 :(得分:1)
git log --oneline -1 OLD_SHA..NEW_SHA
如果这给你一些日志,那么OLD_SHA是NEW_SHA的父母。
答案 4 :(得分: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'