我试图编写一种方法来判断给定提交是否在给定分支的第一个父链上。因此,例如,merge-base不会飞,因为提交可能已合并。我想知道确切的提交是否曾经是分支的一角。
注意:有问题的分支受非快进合并策略的约束。
答案 0 :(得分:1)
无快进策略意味着你可以在git log --first-parent
中进行grep。您可能只想要哈希值,因此您可以使用git rev-list
代替
git rev-list --first-parent | grep <commit hash>
否则使用--format
和git log
来显示所需的数据。
编辑:这篇文章可以给你一些想法
How can I tell if one commit is an ancestor of another commit (or vice-versa)?
答案 1 :(得分:0)
一个简单的&#34;是祖先&#34;测试显然不会做,因为承诺下来的父母连锁店也是祖先:
...o--o--A--o--o--o--T
\ /
...-o--*--B----o
\
C
A
和B
都是T
的祖先,但您希望在拒绝A
和B
时接受C
。 (假设--first-parent
是这里的第一行。)
然而,使用git merge-base
,将实际执行部分工作。您不需要--is-ancestor
的{{1}} 模式,而做需要一些额外的处理。
请注意,无论git merge-base
与某些祖先之间的路径如何,T
的合并基础和该祖先(例如T
或{{ 1}})或者是祖先本身(这里分别是A
或B
),或祖先的一些祖先,如果我们查看A
并提交B
*
作为一对。 (即使在多个合并基础的情况下也是如此,尽管我会向您构建一个证明。)
如果测试提交的合并基础和分支提示的所有一组中的任意一个或任意选择的一个已经不是测试提交,那么我们有一个类似T
和可以拒绝它。 (或者,我们可以使用C
来拒绝它,或者......好吧,请参阅下文。)如果没有,我们必须枚举有关提交之间的祖先路径中的提交。分支小费。对于C
,这是:
--is-ancestor
对于B,这是:
A
如果任何此类提交是 merge 提交,标记为 o--o--*--T
的提交,我们需要确保第一个父提交包含此列出的提交之一路径。最棘手的案例是拓扑上类似于:
*--T
/
o
因为它们之间的*
包括合并和两种方式到达 o--o
/ \
...--A o--T
\ /
o--o
,其中一种是第一父路径,其中一种不是。 (如果--ancestry-path
本身也是合并,那也是如此。)
A
本身不包括T
。此外,添加testcommit..tipcommit
- 丢弃所有本身不属于左侧子项的提交 - 将丢弃testcommit
输出中的所有提交:类似{ {1}}没有后代是--ancestry-path
的祖先(如果确实如此,git rev-list
将是合并基础。)
因此,我们想要的是检查C
中的提交。如果此列表为空,则测试提交首先不是分支提示的祖先。我们有一个像提交T
的案例;所以我们有答案。如果列表非空,则将其减少为其合并组件(使用C
再次运行,或将列表提供给git rev-list --ancestry-path testcommit..branchtip
,以生成缩小的列表)。如果此列表是非 -empty,请通过查找其C
ID并确保结果位于第一个列表中来检查每个合并。
实际(尽管未经测试)shell脚本代码:
--merges
以上测试尽可能少提交提交,但从某种意义上说,运行起来会更加实用:
git rev-list --stdin --merges
如果输出本身包含--first-parent
,那么TF=$(mktemp) || exit 1
trap "rm -f $TF" 0 1 2 3 15
git rev-list --ancestry-path $testcommit..$branch > $TF
test -s $TF || exit 1 # not ancestor
git rev-list --stdin --merges < $TF | while read hash; do
parent1=$(git rev-parse ${hash}^1)
grep "$parent1" $TF >/dev/null || exit 1 # on wrong path
done
exit 0 # on correct path
可以访问,仅来自git rev-list --first-parent ${testcommit}^@..$branch
的第一个父项。 (我们使用$testcommit
排除 $testcommit
的所有父项,这样即使对于根提交也是如此;对于其他提交,branch
就足够了,因为我们可以使用^@
。重新使用$testcommit
。)此外,如果我们确保这是以拓扑顺序完成的,那么从${testcommit}^
命令发出的 last 提交ID将是--first-parent
本身当且仅当git rev-list
可以从$testcommit
访问时。因此:
$testcommit
应该做的伎俩。 $branch
周围的引号以防万一它扩展为空字符串。