查找包含多个特定提交的Git提交

me_*_*and 9 git git-log git-branch git-rev-list

一般问题:给定一组提交,我如何找到所有提交的提交列表作为祖先,或相关地,包含所有这些提交的第一个提交.

我可以通过查找git branch --contains <commit>集合中所有提交返回的分支来查找包含提交的分支(类似标记),但是git rev-list没有--contains选项.实际上,我正在寻找一种方法来组合常规--contains参数git rev-list,并将输出限制为包含所有列出的提交的提交,而不是其中任何一个(这是如何--contains正常工作).

具体的例子:鉴于提交a,b,c,我怎么能找到的第一个承诺是在其祖先的所有三个提交?

例如,给定下面的树,我如何找到标记为X的提交?

* (master)
|
X
|\
a *
| |
b c
|/
*
|
*
Run Code Online (Sandbox Code Playgroud)

我假设我可以做一些魔法git rev-list,并且可能涉及到<commit1>...<commit2>符号,但我不能比这更进一步.

Kyl*_*yle 1

一种可能的解决方案:

使用 'git merge-base ab c' 获取要用作调用 rev-list 的起点的提交;我们将其命名为 $MERGE_BASE。

使用 'git rev-list $MERGE_BASE..HEAD' 调用列出从其共同祖先到 HEAD 的所有提交。循环访问此输出(伪代码):

if commit == a || b || c
  break
else 
  $OLDEST_DESCENDANT = commit
return $OLDEST_DESCENDANT
Run Code Online (Sandbox Code Playgroud)

这适用于上面的示例,但如果它们从未合并,没有在紧随最新的 a、b、c 之后的提交中合并,或者如果有多个合并提交将 a、a 合并在一起,则会给出误报, b 和 c(如果它们各自驻留在自己的分支上)。寻找最古老的后代还有一些工作要做。

然后,您应该遵循上面的内容,以 $OLDEST_DESCENDANT 开头,并在 DAG 中从它向后向 HEAD 前进(rev-list --reverse $OLDEST_DESCENDANT~..HEAD),测试以查看 'rev-list $MERGE_BASE 的输出~..$OLDEST 包含所有所需的提交 a、b 和 c(不过,也许有比 rev-list 更好的方法来测试它们是否可访问)。

正如 twalberg 提到的,像这样单独测试提交似乎不太理想且缓慢,但这是一个开始。这种方法比他的合并提交列表方法具有优势,因为当所有输入提交都在同一分支上时,它将提供有效的响应。

性能主要受到合并基础、头、X 和所需提交集(a、b 和 c)中最新的提交集之间的距离的影响。