排序 Ceph 反向移植分支

loic

当有许多正在进行的反向移植时,它们更有可能相互重叠和冲突。当一个冲突可以轻易解决,因为它来自一个代码块的上下文时,通常只需交换这两个提交就可以完全避免冲突。例如,假设一个提交在

void foo() { } void bar() {}

foo 函数添加一个参数

void foo(int a) { } void bar() {}

而第二个提交给 bar 函数添加一个参数

void foo(int a) { } void bar(bool b) {}

如果第二个提交在第一个提交之前被反向移植,它将发生冲突,因为它会发现 bar 函数的上下文中有没有参数的 foo 函数。

当有几十个反向移植分支时,它们可以被排序,以便第一个合并的是在master分支中选择最旧祖先的。换句话说,根据上面的例子,第一个提交的cherry-pick应该在第二个提交之前合并,因为它在提交历史中更旧。

分支排序还可以优雅地处理相互依赖的反向移植。例如,假设第一个分支包含几个反向移植的提交,而第二个分支包含一个反向移植的提交,该提交除非第一个分支合并否则无法应用。由于每个提议进行反向移植的Ceph分支都必须通过 make check,最常用的策略是将第一个分支中的所有提交都包含在第二个分支中。第二个分支不打算合并,并且标题通常以DNM(Do Not Merge)为前缀。当第一个分支合并后,第二个分支会基于目标进行rebase,并且冗余的提交会从第二个分支中消失。

这是一个实现排序的三行shell脚本

创建一个文件,其中包含master中所有提交的哈希值

但要丢弃那些已经存在于hammer版本中的。

git log --no-merges \ --pretty='%H' ceph/hammer..ceph/master \

/tmp/master-commits

将每个拉取请求与其来源的提交进行匹配

cherry-pick。只使用第一个提交:我们期望其他的提交是

直接的祖先。如果不是这种情况,我们不知道如何

使用该信息,所以我们直接忽略它。

for pr in $PRS ; do git log -1 --pretty=%b ceph/pull/$pr/merge^1..ceph/pull/$pr/merge^2 | \ perl -ne 'print "$1 '$pr'\n" if(/cherry picked from commit (\w+)/)' done > /tmp/pr-and-first-commit

对于每个拉取请求,grep出cherry-picked的提交并显示其

行号。将结果按倒序排序以获得拉取请求

以与cherry-picked提交在master历史中发现的方式相同的方式排序

在master历史中。

SORTED_PRS=$(while read commit pr ; do grep --line-number $commit < /tmp/master-commits | \ sed -e "s/\$/ $pr/" ; done < /tmp/pr-and-first-commit | \ sort -rn | \ perl -p -e 's/.* (.*)\n/$1 /')