Git 如何一次 cherry-pick 多个提交?多个 commit 批量合并完整教程
在实际开发中,我们经常会遇到这种情况:
某个分支上有好几个已经提交完成的改动,但我并不想把整个分支 merge 过来,只想把其中几个 commit 合并到当前分支,该怎么做?
这时候就可以继续使用 git cherry-pick。
上一篇我们讲的是把某一个 commit 合并到当前分支,而这篇专门解决另一个很常见的问题:
如何一次 cherry-pick 多个提交。
这篇会把最常见的几种情况全部讲清楚:
- 一次 cherry-pick 多个不连续的 commit
- 一次 cherry-pick 一段连续的 commit
- A..D 和 A^..D 到底有什么区别
- 多个提交发生冲突怎么办
- 如何中止整个 cherry-pick
- 如何只应用改动,最后合成一个提交
- 多个 commit 的顺序应该怎么写
- 实际开发中应该选择哪一种方式
一、先回顾一下 cherry-pick 是什么
git cherry-pick 的作用可以简单理解成:
从其他位置选中一个或多个已经存在的提交,把这些提交产生的代码改动重新应用到当前分支。
例如现在有两个分支:
feature: A — B — C — D
main: M1 — M2
如果我们只想把 feature 分支中的 B 和 D 放到 main,不想把整个 feature 合并进来,就可以使用 cherry-pick。
这也是它和 git merge 最大的区别之一。
merge 更偏向于合并分支历史,而 cherry-pick 更偏向于精准挑选指定提交。
二、操作前先确认当前分支
这是使用 cherry-pick 时最重要的一步。
因为:
cherry-pick 会把指定提交应用到你当前所在的分支。
假设我们准备把几个提交合并到 main,应该先切换到 main:
git switch main
如果项目里使用的是旧版 Git,也可以使用:
git checkout main
查看当前分支:
git branch
然后确认工作区状态:
git status
正式执行前,最好保证工作区是干净的,不要留着尚未提交的修改。
三、先找到需要 cherry-pick 的 commit
如果不知道提交哈希,可以先查看提交历史:
git log –oneline
例如看到:
8f2a931 fix: 修复订单金额计算问题
51bd822 feat: 增加优惠券校验
9c78a11 refactor: 优化订单查询
3ae24fd feat: 增加订单导出功能
假设现在只需要:
- 8f2a931
- 51bd822
- 3ae24fd
这三个提交。
接下来有几种不同的写法。
四、方法一:一次写多个 commit hash
这是最直观、最好理解,也是我最推荐初学者使用的方法。
语法:
git cherry-pick commit1 commit2 commit3
例如:
git cherry-pick 8f2a931 51bd822 3ae24fd
Git 会依次把这些提交的改动应用到当前分支,并通常为每个提交创建一个新的提交。

这种方式什么时候最适合?
当你需要的提交不是连续的时,这种写法最合适。
例如原分支历史是:
A — B — C — D — E
你只想要:
B、D、E
那就直接写:
git cherry-pick B D E
这样非常直观,也不容易误选其他提交。
五、多个 commit 的顺序重要吗?
重要。
尤其是多个提交之间存在代码依赖的时候。
例如:
A:创建 UserService
B:给 UserService 增加方法
C:调用 B 中增加的方法
如果你先 cherry-pick C,但当前分支还没有 A 和 B,就很可能出现冲突,甚至代码无法编译。
因此,如果几个提交之间存在前后依赖,通常应该按照原来的提交顺序执行。
例如:
git cherry-pick A B C
而不是:
git cherry-pick C B A
所以在操作之前,可以先用下面的命令确认历史顺序:
git log –oneline –reverse
六、方法二:cherry-pick 一段连续提交
如果需要的提交刚好是一整段连续的历史,就没有必要把每个 commit hash 都手动写出来。
例如:
P — A — B — C — D
假设我们希望把 B、C、D 全部 cherry-pick 到当前分支。
可以使用:
git cherry-pick "A..D"
这里最容易理解错的一点是:
A..D 不包含 A。
在简单线性历史中,它表示从 D 可到达、但从 A 不可到达的这一组提交,因此这里得到的是:
B、C、D
七、如果我想连 A 一起 cherry-pick 呢?
还是这个历史:
P — A — B — C — D
如果你希望一次把:
A、B、C、D
全部带过去,可以写:
git cherry-pick "A^..D"
这里的 A^ 表示 A 的父提交。
因此整个范围就会从 A 开始,一直到 D。

可以直接这样记:
| A..D | B、C、D |
| A^..D | A、B、C、D |
这也是批量 cherry-pick 时最容易写错的地方之一。
八、为什么我更推荐初学者直接写多个 commit hash?
虽然范围写法很方便,但是当 Git 历史比较复杂、存在分叉或 merge commit 时,revision range 的实际提交集合可能没有你想象中那么直观。
如果只有两三个或者四五个提交,我更建议直接明确写出来:
git cherry-pick A B C D
优点非常明显:
连续提交非常多时,再考虑使用范围写法会更加方便。
九、执行多个 cherry-pick 后会发生什么?
例如执行:
git cherry-pick A B C
假设三个提交都成功应用。
原来当前分支是:
M1 — M2
执行之后可能变成:
M1 — M2 — A' — B' — C'
需要注意:
虽然 A' 和原来的 A 代码改动可能相同,但它们并不是同一个 Git commit。
因为 cherry-pick 是在当前分支上重新创建提交,所以一般会产生新的 commit hash。
十、多个提交 cherry-pick 到一半冲突了怎么办?
假设执行:
git cherry-pick A B C D
A、B 成功了,但是执行到 C 时发生冲突。
Git 会停下来,不会直接继续执行 D。
这时候先查看状态:
git status
打开冲突文件,可以看到类似:
<<<<<<< HEAD
当前分支中的代码
=======
正在 cherry-pick 的提交中的代码
>>>>>>> C
根据实际需求修改代码并删除冲突标记。
然后将解决后的文件加入暂存区:
git add .
继续执行:
git cherry-pick –continue
Git 完成 C 后,会继续处理后面的提交。

整个流程可以记成:
cherry-pick 多个提交
↓
发生冲突
↓
修改冲突文件
↓
git add .
↓
git cherry-pick –continue
↓
继续处理剩余提交
十一、不想继续了怎么办?
如果发现冲突太多,或者自己 cherry-pick 错了,可以放弃当前这次 cherry-pick 序列:
git cherry-pick –abort
它会尝试把状态恢复到开始这次 cherry-pick 之前。
这是处理批量 cherry-pick 时非常重要的一条命令。
十二、某一个提交不想要了,可以跳过吗?
如果执行过程中停在某个提交,而你确认这个提交不需要继续应用,可以使用:
git cherry-pick –skip
Git 会跳过当前这个提交,然后继续处理后面的提交。
不过不要为了“快速消除冲突”就随便 –skip。
如果后面的提交依赖当前提交,跳过之后可能继续出现问题。
十三、多个提交能不能最后合成一个 commit?
可以。
默认情况下:
git cherry-pick A B C
通常会生成三个对应的新提交。
如果你希望只应用这些提交的改动,而暂时不自动 commit,可以使用 -n 或 –no-commit:
git cherry-pick -n A B C
也可以写:
git cherry-pick –no-commit A B C
执行完成后,这些改动会留在工作区和暂存区中。
然后你可以自己统一提交一次:
git commit -m "feat: 合并订单相关功能"
最终原本多个 commit 的改动,就可以整理成当前分支上的一个新 commit。
十四、什么时候适合使用 –no-commit?
例如原分支上有三个非常小的提交:
A:修改按钮文字
B:调整按钮间距
C:修改按钮颜色
如果目标分支并不需要保留三个独立提交,可以使用:
git cherry-pick -n A B C
检查代码:
git diff –cached
最后统一提交:
git commit -m "style: 优化按钮样式"
这样提交历史会更加简洁。
但如果三个 commit 本身代表三个独立功能,就不建议为了“好看”强行压成一个提交。
十五、实际开发案例
假设团队现在有:
develop
release
develop 中最近有这些提交:
71a2d11 feat: 新增会员首页
82bc933 fix: 修复支付金额计算
93de122 refactor: 重构商品列表
ac4f650 fix: 修复订单重复提交
bd5a761 feat: 新增活动页面
现在 release 分支准备发布,但是只需要把两个 bug 修复带进去:
82bc933
ac4f650
先切换到目标分支:
git switch release
更新目标分支:
git pull
确认状态:
git status
然后一次 cherry-pick 两个修复提交:
git cherry-pick 82bc933 ac4f650
检查提交历史:
git log –oneline -10
测试没有问题之后推送:
git push origin release
这个场景就是 cherry-pick 非常典型的用途:
不合并整个开发分支,只把确定需要发布的几个修复精准带到 release 分支。
十六、常见错误 1:忘记切换到目标分支
很多人查完 commit hash 后马上执行:
git cherry-pick A B C
结果发现提交被加到了错误分支。
所以建议养成一个固定习惯:
git branch –show-current
确认当前分支正确以后,再执行 cherry-pick。
十七、常见错误 2:把 A…D 理解成包含 A
这是最常见的范围误区。
简单线性历史:
P — A — B — C — D
执行:
git cherry-pick "A..D"
不是 A、B、C、D。
而是:
B、C、D
如果 B 的代码依赖 A,而当前分支又没有 A,那么从 B 开始 cherry-pick 甚至可能直接冲突。
要包含 A,可以使用:
git cherry-pick "A^..D"
十八、常见错误 3:多个提交存在依赖却乱写顺序
如果:
A:创建类
B:调用 A 创建的类
C:继续修改 B
最好按照:
git cherry-pick A B C
执行。
不要随便改成:
git cherry-pick C A B
否则可能会让原本可以正常应用的提交变成冲突。
十九、常见错误 4:工作区还有修改就开始操作
开始前建议执行:
git status
如果存在未提交修改,可以根据实际情况先提交:
git add .
git commit -m "chore: 保存当前修改"
或者临时保存:
git stash
然后再执行 cherry-pick。
二十、多个 cherry-pick 和 merge 怎么选?
可以简单按下面的思路判断:
| 整个功能分支都需要 | git merge |
| 只需要其中一个提交 | git cherry-pick |
| 只需要几个指定提交 | git cherry-pick |
| 一整段连续提交需要搬过去 | git cherry-pick + revision range |
| 需要保留完整分支合并关系 | git merge |
| 修复需要回补到旧版本分支 | git cherry-pick |
如果你发现自己准备 cherry-pick 一个分支里几乎所有提交,那就应该重新考虑是不是直接 merge 更合适。
二十一、最常用命令汇总
查看提交历史:
git log –oneline
查看当前分支:
git branch –show-current
一次 cherry-pick 多个指定提交:
git cherry-pick A B C
cherry-pick A 之后到 D 的提交,不包含 A:
git cherry-pick "A..D"
cherry-pick A 到 D,包含 A:
git cherry-pick "A^..D"
只应用多个提交的改动,不立即提交:
git cherry-pick -n A B C
冲突解决后继续:
git add .
git cherry-pick –continue
跳过当前提交:
git cherry-pick –skip
放弃整个 cherry-pick:
git cherry-pick –abort
二十二、最后总结
一次 cherry-pick 多个提交其实并不复杂,最常用的就是下面三种写法。
多个不连续提交
git cherry-pick A B C
连续提交,不包含起点 A
git cherry-pick "A..D"
连续提交,包含 A
git cherry-pick "A^..D"
如果只记住一句话:
提交少、位置不连续时,直接把 commit hash 一个一个写出来;连续提交很多时,再使用 revision range。
同时一定要注意三件事:
掌握这些以后,无论是把多个 bug 修复同步到发布分支,还是把一段功能提交迁移到其他分支,都可以比较安全地完成。
网硕互联帮助中心



评论前必须登录!
注册