ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

一个 MR 不应该只做一件事吗?为什么还需要 Cherry-pick?

一个 MR 不应该只做一件事吗?为什么还需要 Cherry-pick?

很多开发者第一次接触 GitLab 的 Cherry-pick 时,都会有一个疑问:

如果团队开发足够规范,一个 MR(Merge Request)不是应该只完成一个功能或一个 Bug 修复吗?既然如此,为什么还需要 Cherry-pick?

这是一个非常典型的误区。

实际上,Cherry-pick 的价值并不是解决 MR 粒度的问题,而是解决代码发布的问题。


一个优秀的 MR 应该是什么样?

大多数团队都会遵循一个原则:

One MR, One Purpose(一个 MR,只完成一个目标)

例如:

MR1:修复登录 Bug MR2:新增 OAuth 登录 MR3:重构登录模块 MR4:优化登录性能

而不是:

MR: ✓ 修复登录 Bug ✓ 新增 OAuth 登录 ✓ 修改数据库 ✓ 重构代码 ✓ 优化 UI

这样做有很多好处:

  • Code Review 更容易,只需要关注一个目标。
  • CI 出问题时更容易定位原因。
  • 回滚更加简单。
  • Git 历史更加清晰。
  • 每个 MR 都可以独立验证。

所以,一个成熟团队通常都会尽量保持MR 足够小、职责单一


那为什么还需要 Cherry-pick?

关键在于:

Cherry-pick 不是在 MR 中选择,而是在分支中选择。

很多人误以为 Cherry-pick 是:

「这个 MR 里面既有 Bug,又有新功能,所以我要挑一个出来。」

事实上,在规范团队里,这种情况反而很少发生。

真正经常发生的是下面这种情况。


开发分支和发布分支并不是同一个分支

假设团队有这样几个分支:

main (线上) release/2.1 (待发布) develop (日常开发)

开发人员所有工作都提交到develop

例如最近开发了三个 MR:

MR1 修复库存计算 Bug MR2 新增 AI Reply MR3 重构邮件模块

这些 MR 都已经合并到了develop

此时:

develop MR1 MR2 MR3

但是,公司准备发布 2.1 版本。

问题来了:

产品经理决定,这次版本只上线 Bug 修复,不上线新功能。

于是需要得到这样的结果:

release/2.1 ✓ MR1 ✗ MR2 ✗ MR3

这时候就不能直接:

Merge develop → release

因为这样会把 AI Reply、新功能、重构全部带过去。

正确的方法就是:

Cherry-pick MR1 ↓ release/2.1

整个发布过程变成:

develop MR1 MR2 MR3 │ │ Cherry-pick ▼ release/2.1 MR1

可以看到,Cherry-pick 选择的是「哪个 MR 进入哪个分支」,而不是「MR 里面选择哪些 Commit」。


为什么不直接把 MR 合并到 Release?

因为不同分支承担着不同职责。

例如:

develop

意味着:

最新开发成果。

可能包含:

  • 新功能
  • 实验功能
  • 重构
  • Bug 修复

而:

release/2.1

意味着:

即将上线的稳定版本。

通常只允许:

  • Bug 修复
  • 安全修复
  • 极少量稳定改动

因此,Release 分支必须尽可能保持稳定。

Cherry-pick 就成为了连接这两个分支的桥梁。


热修复(Hotfix)也是一样

还有一种更常见的情况。

线上运行的是:

main

开发人员发现一个严重 Bug。

修复之后,代码首先进入:

develop

但是线上用户已经受到影响。

这时候不能等待下一次版本发布,而需要立刻修复线上。

于是:

MR Fix login bug │ ├────────► develop │ └─Cherry-pick──► main

这样:

  • 开发分支继续正常开发。
  • 线上立即获得 Bug 修复。
  • 新功能不会提前发布。

这就是 Hotfix 最经典的流程。


为什么大家会误解 Cherry-pick?

原因在于很多教程都会举这样的例子:

MR Commit1 修 Bug Commit2 新功能

然后:

Cherry-pick Commit1

虽然 Git 的确支持这种操作,但这并不是 Cherry-pick 最重要的使用场景。

如果一个团队经常需要从一个 MR 中挑 Commit,反而说明:

MR 拆分得不够合理。

真正优秀的开发流程应该是:

MR1 Fix Login Bug MR2 Add OAuth MR3 Refactor Login

这样 Cherry-pick 时,直接选择整个 MR 即可,不需要再从里面挑 Commit。


总结

很多人认为:

一个 MR 应该只完成一件事,所以 Cherry-pick 没什么意义。

实际上,这两件事情并不冲突。

  • MR 的职责:保证一次开发只解决一个问题,方便 Review、测试和回滚。
  • Cherry-pick 的职责:决定哪些修改进入哪个分支,方便版本发布和热修复。

换句话说:

MR 是开发维度的管理工具,而 Cherry-pick 是发布维度的管理工具。

开发阶段,我们追求的是小而独立的 MR

发布阶段,我们追求的是只把需要的修改发布到目标分支

正因为 MR 足够独立,Cherry-pick 才能发挥最大的价值:精准地将一个已经验证完成的修改,同步到需要它的分支,而不会夹带任何无关代码。

返回列表