我正在尝试确定由于使用合并 ID 进行合并而引入父分支的提交。
3 回答
命令git log <id>~1..<id>
将列出所有合并的提交,以及合并提交本身。
TL;博士
使用max630 的答案,只要它是真正的合并。要排除合并本身,请使用它的轻微变体:M^1..M^2
.
长
您在这里要求的是找到由于合并而变得可访问的提交。这种可达性思想是一个图论概念。因此,如果你画出合并的结果,答案就更清楚了。
找到合并基地
假设“合并前”图如下所示,*
合并基础提交在哪里,L
并且R
是左侧和右侧提示提交:
...--*--...--L <-- mainline
\
o--...--R <-- sidebranch
然后“合并后”图如下所示:
...--*--...--L---M <-- mainline
\ /
o--...--R <-- sidebranch
显然,新引入的提交是 :-) 沿着底行的提交,即那些可从(包括)到达R
的提交,但不包括合并基础提交。我们从 的第二个父节点开始到达它们M
,即R
,然后沿着从R
其父节点到另一个父节点的反向连接工作,依此类推。这些通向底部o
节点,该节点连接回 commit *
。
如果你有一个像sidebranch
指向的名字R
,你只需要找到合并基础:
mb=$(git merge-base $all mainline^1 sidebranch)
它使用“提交的第一个父级”语法来识别L
来自 commitM
的提交:^1
后缀。如果您不再拥有 name ,则可以使用“提交的第二个父项”语法sidebranch
来识别提交:R
mb=$(git merge-base $all mainline^1 mainline^2)
不幸的是,这不是唯一可能的输入图。具有如下所示的“合并前”图是非常典型的:
...--* <-- mainline
\
o--...--R <-- sidebranch
git merge
不运行--no-ff
将执行“快进”操作,这实际上不是合并:您最终得到一个线性图并且没有合并提交:
...--*--o--...--R <-- mainline, sidebranch
在这里,除非您仍然有主线分支的 reflog 条目,否则实际上是不可能找到 commit*
的。如果您确实有 reflog 条目,这很简单:它是,使用适当的. (找到合适的就是通过 reflog 查找来自快进的更新。如果您刚刚进行了合并,那么它就是并且也是。)mainline@{number}
number
number
1
HEAD@{1}
mb=$(git rev-parse mainline@{1}) # for instance
我$all
在上面的示例命令中放入用于查找合并基础的原因是,当您有多个合并基础时,还有第三种可能性:
...--o--*---o--...--L
\ /
X
/ \
...--o--*---o--...--R
在这里,您将要排除所有合并基础。必要时$all
更换。--all
现在您拥有所需的一切
既然您知道了合并基础,git merge-base
如果合并是真正的合并,已经找到了它们,合并可以访问的提交只是那些可以从R
自身访问的提交,而不是从合并基础可以访问的提交:
git rev-list sidebranch --not $mb
如果您想检查提交而不是简单地枚举它们,请使用git log
而不是。git rev-list
简化这个
以上所有内容旨在找到合并基础并排除它们,以便我们获得提交R
及其可到达的祖先,而无需从L
. 但是我们不必专门从合并基础开始这个排除。我们可以从它L
本身开始。
要命名L
,我们只需要命名mainline
merge 的前一个值或第一个父级M
。的第一个父级M
是M^1
or M~1
,所以只要我们知道 的哈希 ID M
,我们就可以添加后缀并说“排除这些”。
甚至还有一个简写语法。代替:
git rev-list M^2 --not M^1
或略短:
git rev-list M^2 ^M^1
我们可以使用两点语法:
git rev-list M^1..M^2
这就是我们在顶部所拥有的。
请注意,所有这些都假定“真正的合并”:如果合并是快进,则必须改用 reflog。
您可以签出分支并使用 git log 查看分支中的提交和提交 ID。
git log -n10 --oneline
将为您提供该分支中前 10 次提交的历史记录。