TL;DR(但未经测试)
作为一个shell脚本:
git rev-list --merges HEAD |
while read rev; do
thistree=$(git rev-parse $rev^{tree})
p1tree=$(git rev-parse $rev^1^{tree})
if [ $thistree = $p1tree ]; then
echo "commit $rev has the effect of -s ours"
fi
done
长
直接的答案是“不”(但请继续阅读)。 实际使用的策略不会自动记录。 (如果进行所有合并的人非常自律,也许他们在每条合并提交消息中都记录了该信息。根据您的问题描述,这显然没有发生......)但这不一定是有趣的问题反正。有人可以创建具有-s ours 的效果 的合并,而无需实际使用ours 策略。
更有趣的问题是自动查找具有-s ours 的效果的合并,无论是否使用了该选项;并且 很容易实现自动化。
问题简化为:
- 查找合并提交:用于此的工具是
git rev-list。
- 测试合并提交以查看它们是否具有
-s ours 的效果:用于此的工具是......好吧,见下文;有几种可能性。
一旦您知道git rev-list 如何枚举提交,查找合并提交就很简单了。与git log 一样,您给git rev-list 一个起点,然后Git 从该点向后 工作,通过从该提交可访问的历史,直到它用完历史或遇到提交你已经告诉它用作停止点。
通常,一个好的起点是HEAD,这是您现在签出的提交,可能是分支的提示提交。你甚至可以给出多个起点,例如--branches(每个分支的每个提示)或--all(每个带有标签的提交,无论该标签是分支名称、标签名称、远程跟踪名称还是甚至是像 refs/stash 这样的特殊名称之一。
然后您希望将输出限制为仅列出合并提交。合并提交是具有至少两个父级的任何提交:--min-parents=2。不过,有一个您可能更喜欢的同义词,所以我们得到,例如:
git rev-list --merges HEAD
从您现在的位置开始,并通过从HEAD 访问的所有提交向后工作。 (有关此可达性概念的更多信息,请参阅Think Like (a) Git。)
git rev-list 的输出是符合rev-list 标准的提交哈希ID 流,在本例中为--merges(每个可到达的合并提交):对人类不是很有用,但对计算机程序很有用。现在我们只需要编写识别有趣合并的程序。
我们已经看到合并提交是至少有两个父级的提交。 -s ours 或等效项所做的是告诉 Git 新合并提交的快照(其存储的树)应该匹配两个父级之一,特别是 first 父级。您可能想要放宽您的条件并检查树是否与第二个父级的树匹配(theirs-strategy 合并,除了-s theirs 没有内置),或者对于章鱼合并,任何 的父母,但“匹配第一父母”可能会这样做,而且稍微容易一些。
两种明显的方法是:
- 将合并提交的树与其第一个父级的树进行比较:
git diff(或其管道等效项)与两个特定的提交或树哈希。
- 或者,由于我们只关心整棵树,直接比较顶层树哈希即可。这会检查纯粹的完全匹配;如有必要,使用完整的
git diff 或等效项可以让您稍微放宽匹配标准。
我们将在 shell 脚本中编写第二个代码——比较存储在合并中的 tree 哈希和它的第一个父级中的哈希值——因为它可能更快,并且无论如何演示了更多的各种 Git 工具。我们从通用的“读取每个提交哈希”循环开始:
while read rev; do ...; done
每个版本都将在循环中以$rev 的形式提供。
现在我们只需将$rev(提交)变成它自己的树:
git rev-parse $rev^{tree}
它使用the gitrevisions syntax 来查找指定提交的树哈希ID。我们必须将它保存在一个变量中:
thistree=$(git rev-parse $rev^{tree})
然后我们想要找到第一个父节点的树。在 gitrevisions 语法中,第一个父级是 ${rev}^1。这里的大括号在技术上是不必要的,所以我会省略它们。然后我们想要那个提交的树,我们需要将它保存在另一个变量中:
p1tree=$(git rev-parse $rev^1^{tree})
如果两棵树匹配,则提交$rev具有-s ours的效果,无论它是否使用-s ours,所以我们应该打印它的哈希ID,甚至在上面运行git show。
这个循环的最终版本(将所有部分放在一起)是这个答案顶部的那个。