审查 rebase 后的提交,可以试试 git range-diff

48 次浏览6 条回复

分支 rebase 过、提交号全变了时,直接拿两段 commit 区间比 diff 不太直观。Git 自带的 range-diff 可以按提交对比两组 patch,看看每个提交的改动有没有在改写后保留下来。环境:Git 2.19+。

git range-diff main..feature~3 main..feature

上面假设 feature 最近整理成了 3 个提交,前一组是整理前的提交区间,后一组是整理后的区间。实际使用时把两个区间换成 rebase 前后各自的基线和分支范围。

如果只想看某次合并前后的两组提交,也可以先记下旧分支指针,再运行:

git range-diff old-feature..old-feature~3 new-feature~3..new-feature

输出里的 = 表示补丁基本对应,! 表示对应提交内容发生了变化,< 或 > 表示一边独有的提交。它比较的是 patch 内容,不是 commit id;提交拆分或合并时结果可能需要人工判断。

这个命令对整理提交很有用。一个容易踩的点是,两边区间的基线要对应同一个分支分叉点;如果 rebase 前后的指针都还在,可以先用 git merge-base 找共同基线,再把旧提交范围和新提交范围传给 range-diff。另外提交拆分或合并后,= 不一定能一一对应,看到 ! 最好再打开具体 patch 看,别只按提交数量判断。

补一个实用参数:如果两组提交改动差异比较大,默认匹配可能不太理想,可以试试 --creation-factor=<n> 调整 patch 相似度阈值,例如 git range-diff --creation-factor=80 old-base..old-feature new-base..new-feature。它只影响提交之间的匹配,不会改变实际 diff;匹配结果异常时,还是要结合文件改动确认。

我会在 rebase 前先给旧分支打个临时 tag,比如 git tag before-rebase feature,这样即使后面强推了,也能明确拿旧指针和新指针做对比:git range-diff old-base..before-rebase new-base..feature。比依赖 reflog 更适合把审查命令留在 PR 记录里。

FinleyLv1#3

我会在 rebase 前先给旧分支打个临时 tag,比如 git tag before-rebase feature,这样即使后面强推了,也能明确拿旧指针和新指针做对比:git range-diff old-base..before-rebase new-base..feature。比依赖 reflog 更适合把审查命令留在 PR 记录里。

还有个范围上的细节:A..B 实际只取 B 中不在 A 的提交,所以两边最好分别固定 rebase 前后的基线和分支指针,别直接把当前 main 套到旧指针上。比如 git range-diff old-base..before-rebase new-base..feature。如果上游分支期间也变过,这样不容易把基线变化误判成业务提交的改动。

隔壁空白Lv1#4

还有个范围上的细节:A..B 实际只取 B 中不在 A 的提交,所以两边最好分别固定 rebase 前后的基线和分支指针,别直接把当前 main 套到旧指针上。比如 git range-diff old-base..before-rebase new-base..feature。如果上游分支期间也变过,这样不容易把基线变化误判成业务提交的改动。

如果要把结果放进 CI 日志,我还会加 --no-dual-color,避免双重配色把终端控制符写进构建产物:git range-diff --no-dual-color old-base..before-rebase new-base..feature。本地终端看彩色输出更直观,非交互日志则关掉颜色,后面检索和比对都省事。

这个思路放进 PR 检查时,还可以把两组范围先展开成明确的提交列表留在日志里:git rev-list --reverse old-base..before-rebase 和对应的新范围各跑一次。这样 range-diff 出现 ! 或匹配数量不一致时,能先确认是不是提交拆分、合并导致的,不会把范围写错误判成代码变化。