Cherry-pick — 是一个 Git 命令,它将一个或多个现有提交中的更改应用到当前分支。与 Merge(转移整个分支)和 Rebase(转移一系列提交)不同,cherry-pick 只选择指定的提交。根据 git-scm.com, 2025,cherry-pick 在发布分支之间转移修复的场景中最受欢迎。
要点
Cherry-pick — 是一个 Git 命令,它复制指定提交中的更改,并将其作为新提交应用到当前分支。这个名称来源于"摘樱桃"的比喻:开发人员只选择需要的提交,忽略其余的提交。
与 Merge 不同,cherry-pick 不会创建合并提交,也不需要完全合并分支。与 Rebase 不同,cherry-pick 不会转移一系列提交——只转移指定的提交。这使得 cherry-pick 成为精准转移修复的理想工具。
根据 Atlassian, 2025 的数据,cherry-pick 在 47% 同时处理多个发布分支的团队中使用。Cherry-pick 在移动开发中尤其受欢迎,因为移动开发需要同时支持多个应用版本(LTS 版本),并且需要在它们之间转移修复。
执行 cherry-pick 时,Git 计算指定提交与其父提交之间的 diff,然后将此 diff 应用到当前分支。如果更改无冲突地应用——Git 创建一个具有相同消息但新 SHA 的新提交。如果存在冲突——cherry-pick 暂停等待手动解决。
Cherry-pick 的语法很简单:指定要转移的提交的哈希值。Git 会将更改复制到当前分支作为新提交。支持同时转移多个提交以及整个范围。
# 将一个提交转移到当前分支
git cherry-pick a1b2c3d4
# 转移多个提交
git cherry-pick a1b2c3d4 e5f6g7h8
# 转移提交范围(从 a1b2 到 f9e8,不包括 a1b2)
git cherry-pick a1b2c3d4..f9e8d7c6
执行 cherry-pick 后,当前分支获得一个包含原始更改的新提交。提交消息默认从原始提交复制,但可以使用 -n(不创建提交)或 --edit(编辑消息)标志进行更改。
考虑一个典型场景:在 develop 中发现并修复了一个严重错误,该错误也存在于发布分支 release/v2.0 中。只需要转移此修复,而无需将整个 develop 合并到发布分支。
# 在 develop 中找到包含修复的提交哈希
git log --oneline develop
# a1b2c3d fix: null check in payment processing
# 切换到发布分支
git checkout release/v2.0
# 应用修复
git cherry-pick a1b2c3d4
# 如果有冲突——解决并继续
git add src/payment/PaymentProcessor.kt
git cherry-pick --continue
-x 标志在提交消息中添加对原始 SHA 的引用:"(cherry picked from commit a1b2c3d4)"。这有助于追踪提交的来源。建议在所有场景中使用 -x,但临时草稿除外。
发生冲突时,cherry-pick 的行为类似于 merge:Git 停止并标记冲突文件。开发人员解决冲突,执行 git add,然后执行 git cherry-pick --continue。要取消——git cherry-pick --abort。--strategy 标志允许指定合并策略(例如,带选项的 recursive)。
# 解决 cherry-pick 时的冲突
# Git 显示冲突文件
git status
# 手动解决,然后:
git add 允许文件.kt
git cherry-pick --continue
# 或者取消 cherry-pick:
git cherry-pick --abort
Cherry-pick 在需要在不合并整个分支的情况下精准转移更改的场景中是最优的。让我们看看 cherry-pick 成为最佳选择的五种主要情况。
对于移动开发,cherry-pick 在支持多个应用版本时至关重要。例如,如果在已在 Google Play 发布的 3.2 版本中发现错误,而 develop 包含 4.0 版本的代码——cherry-pick 允许在不合并所有 breaking changes 的情况下将修复转移到 v3.x 分支。这对于同时支持两个或更多具有不同 API 和依赖关系的主要版本的项目尤其重要。
实践示例:在移动应用中,发现了在 Android 12 上通过 Google Sign-In 授权时的崩溃。修复已纳入 develop 并通过了审查。但当前发布分支 v2.5 已处于 beta 测试阶段。从 develop 到 release/v2.5 的修复提交的 cherry-pick 允许将修复包含在下一个版本中,而无需转移其他尚未准备好发布的更改。
在移动项目中使用 cherry-pick 时,重要的是要考虑依赖关系:如果修复影响在发布分支分歧点之后在 develop 中修改的文件,cherry-pick 可能会带来不完整的更改集。在这种情况下,需要检查所有相关更改是否也已转移,否则应用可能无法编译或工作不正确。在将更改推送到公共分支之前,始终在 cherry-pick 后检查构建。
Git 中集成更改的三个主要工具——merge、rebase 和 cherry-pick——解决不同的任务。选择取决于需要转移多少更改以及历史应该如何呈现。
| 标准 | Merge | Rebase | Cherry-pick |
|---|---|---|---|
| 范围 | 整个分支 | 一系列提交 | 选定的提交 |
| 历史 | 保留分支结构 | 线性 | 线性 |
| 合并提交 | 是(除了 ff) | 否 | 否 |
| 自动化 | 完全 | 链式 | 仅指定 |
| 对于公共分支 | 安全 | 危险 | 安全 |
Merge——当需要完整合并两个分支并保留分支信息时。Rebase——当需要将个人分支更新到具有干净历史的当前状态时。Cherry-pick——当只需要一个或几个选定的提交时。
在实践中,这些工具是组合使用的:功能开发通过定期 rebase 到 develop 进行,然后通过 --no-ff merge 合并,并在需要将修复转移到其他分支时使用 cherry-pick。每个工具在各自的阶段解决各自的任务。
Cherry-pick——是一个有用但如果不正确或过度使用可能带来风险的工具。主要风险与提交重复、上下文丢失以及后续合并中的冲突有关。
风险最小化建议:始终使用 -x 标志指定原始 SHA,在提交消息中记录 cherry-pick 的原因,并在上下文允许时尽可能使用 merge 而不是 cherry-pick。如果 cherry-pick 数量过多——考虑重组分支。
CI 流水线应将 cherry-pick 视为单独的场景。建议设置自动检查:在创建 cherry-pick 提交时,CI 检查修改的文件是否符合预期集合并对受影响的模块运行测试。这降低了在分支之间精准转移更改时回归的风险。
常见问题
Cherry-pick 将更改从一个提交转移到另一个分支。Revert 创建一个新提交,用于撤销同一分支中指定提交的更改。Revert 不会删除历史——它添加反向更改。
可以:git cherry-pick A B C——按顺序转移提交 A、B 和 C。或者 git cherry-pick A..C——转移从 A 到 C 的所有提交(不包括 A)。转移顺序与命令中的顺序一致。
默认情况下,cherry-pick 不适用于合并提交,因为合并提交有两个父提交。使用 -m 1 标志指定与哪个父提交比较。-m 1 相对于第一个父提交获取 diff。
取消 cherry-pick 可以通过 git reset --hard HEAD~1 完成,如果这是最后一个提交。如果提交已推送——使用 git revert <SHA> 创建撤销提交。
没有意义,但技术上是可行的。如果提交已存在于分支中,Git 将检测到更改已应用并报告:"The previous cherry-pick is now empty, possibly due to conflict resolution."提交不会再次创建。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。