排序 Ceph 反向移植分支
当有许多正在进行的反向移植时,它们更有可能相互重叠和冲突。当一个冲突可以轻易解决,因为它来自一个代码块的上下文时,通常只需交换这两个提交就可以完全避免冲突。例如,假设一个提交在
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 /')