讲解
merge 把一个分支的全部提交都并进来,但有时你只要其中一个。经典场景:在开发分支上连续提交了几个改动,其中一个是紧急 bug 修复,需要立刻合回主线上线,其余功能还没准备好——git cherry-pick 提交哈希 就是干这个的:它把指定提交的「改动」复制成当前分支上的一个新提交(内容相同,哈希不同),其余提交原封不动地留在原分支。
cherry-pick 的用法灵活:git cherry-pick 哈希 摘一个;git cherry-pick A B C 摘多个;git cherry-pick A..B 摘一个区间(不含 A,含 B)。它同样是「重放改动」,所以也可能冲突——比如目标分支上相关代码已经变了。冲突时的流程和 rebase 一致:解决冲突、git add、git cherry-pick --continue;想放弃用 git cherry-pick --abort。不想立刻提交(比如想把几个摘取合并成一次提交)可以加 -n(--no-commit),改动只进暂存区。
cherry-pick 的代价是产生「重复提交」:同一个改动在两个分支上是哈希不同的两个提交,将来两个分支整体合并时大概率会再碰面(Git 通常能识别内容相同自动跳过,但历史里看着会乱)。所以它适合「定向搬运」——hotfix 回合主线、把误提交到错分支的提交挪走;常规的功能整合还是用 merge 或 rebase。摘取时加 -x 会在提交信息里记录来源哈希,方便日后追溯,团队协作时推荐。
示例
hotfix 分支上有两个提交,只把紧急修复挑回 main:
git switch -c hotfix
echo "紧急修复" > fix.txt
git add fix.txt
git commit -qm "fix: 紧急修复"
echo "附带改动" > extra.txt
git add extra.txt
git commit -qm "chore: 附带改动"
git switch main
git log --oneline hotfix
git cherry-pick hotfix~1
git log --oneline -2
ls
hotfix~1 就是「fix: 紧急修复」那个提交。摘取完成后 ls 能看到 fix.txt 出现在 main 的工作区,而 extra.txt 没有跟过来——只有被摘的提交过来了。
常见坑
- 以为摘取后原提交消失了:cherry-pick 是复制不是移动,原分支上的提交还在。想「挪走」要先摘取再到原分支 reset 掉它。
- 区间边界记错:A..B 不包含 A 本身,想包含起点要写 A^..B。摘之前先 git log --oneline A..B 确认名单。
- 摘取顺序错误:多个提交有依赖时,必须按原始顺序摘(旧的在前),否则容易冲突或得到错误内容。
- 滥用 cherry-pick 代替合并:长期靠摘取同步两个分支,历史里全是重复提交,越来越乱。它是一把精准的手术刀,不是常规运输工具。
小结
cherry-pick 把指定提交的改动复制到当前分支,支持单个、多个、区间和 -n 暂存模式;冲突用 --continue/--abort 处理;-x 记录来源。它是定向搬运工具,常规整合仍归 merge/rebase。下一章看看团队级的话题:分支协作模型。