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 到新的基点上。