如何高效扁平化Mercurial单父变更链?避免手动合并且提速
Mercurial变更链高效扁平化方案
问题背景
有一长串仅含单个父节点的Mercurial变更,部分变更存在冲突、部分无冲突。需要在不触发手动合并的前提下,将变更序列“扁平化”以最小化树结构深度。原实现脚本通过逐次将变更重定基到祖父节点来完成,但长变更链下速度极慢:
#!/bin/bash for rev in $(hg l --template "{node}" | egrep --only-matching "[0-9a-f]+") do while : do # Attempt to rebase the revision on top of its grandparent. hg rebase -s $rev -d "first(parents(parents($rev)))" if [ $? -eq 0 ] then # Find the updated revision after the rebase. rev=$(hg log --hidden --rev "$rev" | egrep rewritten | egrep --only-matching "[0-9]{4}[:][0-9a-z]+") else hg rebase --abort break fi done done
高效替代方案
1. 批量定位最远无冲突祖先
原脚本的核心问题是每次仅将变更跳一级祖先,导致大量重复的hg命令调用。优化思路是直接为每个变更找到最远的可无冲突变基的祖先,一次完成跳转,减少操作次数:
#!/bin/bash # 按从新到旧的顺序获取所有待处理变更(避免重写后影响后续处理) revs=$(hg log --template "{node}\n" --rev "not public() and only()") for rev in $revs; do # 获取当前变更的所有祖先(从最早到最近排序) ancestors=$(hg log --template "{node}\n" --rev "ancestors($rev) and not $rev" | tac) current_rev=$rev for ancestor in $ancestors; do # 尝试变基到当前祖先 hg rebase -s $current_rev -d $ancestor --quiet if [ $? -eq 0 ]; then # 更新为变基后的新节点 current_rev=$(hg log --hidden --rev "$current_rev" --template "{rewritten}\n" | cut -d' ' -f2) else hg rebase --abort break fi done done
2. 使用histedit扩展批量重写历史
Mercurial的histedit扩展提供了更高效的历史重写能力,可直接在编辑界面调整变更位置,避免shell循环的开销:
- 先启用扩展,在
.hgrc中添加:
[extensions] histedit =
- 运行命令打开历史编辑界面:
hg histedit --rev "root()::tip" # 指定需要处理的变更范围
- 在编辑界面中,将需要扁平化的变更的操作从
pick改为rebase,并指定目标祖先节点。保存后Mercurial会一次性完成所有重定基操作,效率远高于逐次命令调用。
3. 批量筛选可无冲突变基的变更
利用Mercurial的rebase --dry-run批量识别能直接变基到根节点的变更,一次性处理:
# 获取根节点的哈希值 root_node=$(hg log --template "{node}\n" --rev "root()") # 批量筛选可无冲突变基到根节点的变更 valid_revs=$(hg rebase --dry-run -s "not public() and only()" -d $root_node 2>&1 | grep "can rebase" | awk '{print $NF}') # 批量变基这些变更 if [ -n "$valid_revs" ]; then hg rebase -s "$valid_revs" -d $root_node fi # 对剩余变更重复上述逻辑,直到无法继续扁平化
优化核心
- 减少
hg命令调用:原脚本每次循环多次启动Mercurial,批量处理可大幅降低启动开销。 - 跳过中间步骤:直接定位最远可行祖先,避免逐次跳级的冗余操作。
- 利用原生工具:
histedit等内置扩展为原生实现,比shell脚本的循环操作效率更高。
内容的提问来源于stack exchange,提问作者Loren Van Spronsen
相关产品推荐
相关产品推荐

