git-log:具有拓扑排序的合并提交的祖先分支的输出顺序

git-log: output order of ancestor branches for a merge commit with topological ordering

我的项目中有一段代码依赖于这个命令的输出:

git log -n 2 --topo-order --pretty=format:"%H"

这适用于 master 分支上的合并提交(合并的拉取请求),并假定结果是当前(合并)提交和来自功能分支[=28]的父提交的散列=].例如

master   a - b - m
          \     /
feature    x - y 

在合并提交 m 上执行时,假定结果将是 m y 而不是 m b。我通过检查多个这样的合并提交来验证确实是这种情况 - 总是返回功能分支的父级。但是,在 git-log --topo-order 的文档中,我看到没有保证首先打印哪个父分支。

任何人都可以解释当使用 git-log --topo-order 时如何选择先打印哪个父分支以及为什么它总是在我的用例中首先显示功能分支?

内部git log 算法是将“新的”(未访问的)提交插入优先级队列。整体循环为:

while queue is not empty:
    commit = queue.remove_front()
    ... deal with commit ...

其中 deal with 代码可以将提交的 parent(s) 插入队列。

--topo-order 开关简单地(或 complicated-ly,视情况而定)修改提交的 优先级 作为 Git 行进沿着合并的两条腿,这样你就可以从一条腿上得到所有东西,然后从另一条腿上得到所有东西。

一样,文档明确说明未指定 parent 排序。这允许 Git 实现在将来切换到新算法,可能会选择不同的“起始段”。所以依赖于你现在得到的东西是不明智的。

(我 认为 你现在得到的是 parent 提交按 committer-date 顺序排序,所以如果 parent #1 has an committer timestamp than parent #2, git log --topo-order will first trace leg-two 但是这段代码非常乱,有很多暗角,所以我不是愿意说肯定是这样的。)

如果您知道您在某个变量 $H 中有一个合并提交哈希 ID,或者通过某个名称找到 $name,这是获取此哈希 ID 和 parent hash ID,按这个顺序,就是用git rev-parse来做:

git rev-parse ${H} ${H}^2

或:

git rev-parse ${name} ${name}^2

请注意,如果您有一个任意表达式 $expr 并且 git rev-parse 可以转换为哈希 ID,明智的做法是在添加 ^2 后缀以获得第二个之前执行一次parent。那是因为某些表达式会“消耗”后缀。例如,gitrevisions 语法 :/fix nasty bug 是在提交消息中搜索该文本的有效方法。添加 ^2 会产生 :/fix nasty bug^2,它会搜索 bug^2,而不是先找到哈希,然后再移动到第二个 parent。所以:

H=$(git rev-parse ${expr}) || exit
H2=$(git rev-parse ${H}^2)

是在 shell 脚本中编写将表达式转换为所需的两个哈希 ID 的命令的可靠方法。