前端知库

git cherry-pick 和 git bisect 分别解决什么问题?

cherry-pick 把指定提交引入的修改重新应用到当前分支,生成哈希不同的新提交,常用于把修复移植到发布分支;bisect 在一个已知正常、一个已知有问题的提交之间二分查找,定位第一个引入问题的提交,可以配合脚本用 bisect run 自动执行。

参考答案

简答

  • git cherry-pick <提交> 计算该提交相对父提交的修改,应用到当前分支并生成新提交。新提交的哈希与原提交不同。
  • -x 会在提交说明末尾追加 (cherry picked from commit ...),方便以后追溯修复来自哪里。
  • git bisect 需要一个坏提交和一个好提交,每一步检出中间的提交让你标记 good 或 bad,大约 log2(N) 步就能找到第一个坏提交。
  • git bisect run <命令> 用命令的退出码自动标记:0 为好,125 表示跳过,1 到 127 之间的其他值为坏,128 及以上会中止整个 bisect。结束后用 git bisect reset 回到原来的分支。

cherry-pick

典型场景是主干已修复,线上维护的 release 分支也需要这个修复:

bash
git switch release/1.2
git cherry-pick -x 71b8558

遇到冲突时,解决后 git add 再 git cherry-pick --continue,放弃则 git cherry-pick --abort。挑选合并提交需要 -m <父编号> 指定主线。

同一修改在两个分支各有一个提交,之后两分支合并时 Git 通常能识别内容相同,但如果其中一边又改了同一处,仍可能冲突。大量 cherry-pick 往往说明分支策略需要调整,参见《git merge 与 rebase 应该怎样选择?》。

bisect

bash
git bisect start HEAD v1.0   # 先坏后好
# Git 检出中间提交,测试后标记
git bisect good   # 或 git bisect bad
# 重复直到输出 "<哈希> is the first bad commit"
git bisect reset

能用命令判断好坏时交给 bisect run:

bash
git bisect start HEAD v1.0
git bisect run npm test
git bisect reset

测试命令本身在某些提交上无法运行(例如依赖装不上)时,脚本应返回 125,让 Git 跳过这个提交,而不是误判为坏。脚本因被信号终止等原因返回 128 及以上的值时,Git 会报错并停止 bisect,不会把当前提交标记为坏。

常见追问

  • bisect 前要注意什么?工作区要干净,测试脚本最好放在仓库外或不受历史版本影响的位置,否则检出旧提交时脚本可能不存在。
  • 问题时有时无怎么办?二分依赖每一步判断准确,偶发问题要先找到稳定复现方式,或在脚本中多次运行再给出结论。
  • cherry-pick 和 rebase 有什么关系?rebase 可以看成把一串提交依次 cherry-pick 到新的基点上。