Git篇-高危代码修复的“隐形陷阱”:为什么Cherry-pick让你的Tag追溯失效了?

一、背景引入

在最近的一次版本发布过程中,我们遇到了一个典型的Git操作问题。当时,我们有一个高危代码修复需要同步到60、62、63等多个版本分支。同事的做法是:基于60创建hotfix分支,然后在62、63分支上分别拉取hotfix分支,再分别执行cherry-pick操作将修复提交复制过去。表面上看,代码同步成功了,各分支都包含了修复。

但重点问题在于:当后续需要追溯这个修复影响了哪些tag版本时,执行git tag --contains <commit-hash>(哈希码是低版本的代码提交记录值)却只能找到60分支的tag,62、63分支的tag完全没有被包含进来。

为什么会这样?

  • 因为相同的代码改动,在不同分支上通过cherry-pick产生了完全不同的commit hash值。

二、问题复现场景

常用命令准备

# 查看包含commit的tag
git tag --contains <commitId>

# 标签
# 创建本地标签
git tag <tag-name>

# 推送单个标签
git push origin <tag-name>

# 删除本地标签
git tag -d <tag-name>
# 删除远程标签
git push origin --delete <tag-name>

本地快速复现问题

cherrypick方式实现多版本分支修复(复现问题)

首先我们准备两个release分支,一个release_1.1.x、一个release_1.2.x。

首先我们基于release_1.1.x创建一个分支hotfix_1.1.x_tt1,并进行一次代码提交:

image-20260318133731686

当前的哈希码为:96d60ae7

接着我们来对release_1.2.x分支来进行创建一个分支hotfix_1.2.x_tt2,然后从hotfix_1.1.x中的提交记录给cherry pick过来:

image-20260318141256289

当前的哈希码为:eae3f452

接着我们分别在hotfix_1.1.x_tt1中创建一个tag叫做v1.1.1:

git tag v1.1.1

然后切换到hotfix_1.2.x_tt2中也创建一个tag叫做v1.2.1:

git tag v1.2.1

接下来,我们使用一开始hotfix_1.1.x_tt1的哈希码来进行搜索下:

git tag --contains 96d60ae7

image-20260318141613049

你可以发现搜索同一份代码相关的tag只能够搜索到v1.1.1。

merge方式实现多版本分支修复

首先我们准备两个release分支,一个release_1.1.x、一个release_1.2.x。

首先我们基于release_1.1.x创建一个分支hotfix_1.1.x_tt1,并进行一次代码提交:

image-20260318133731686

当前的哈希码为:96d60ae7

接着我们来对release_1.2.x分支来进行创建一个分支hotfix_1.2.x_tt2,然后将hotfix_1.1.x_tt1代码来进行合并过来:

image-20260318141903901

此时的提交记录为:

image-20260318141952759

接着我们分别在hotfix_1.1.x_tt1中创建一个tag叫做v1.1.1:

git tag v1.1.1

然后切换到hotfix_1.2.x_tt2中也创建一个tag叫做v1.2.1:

git tag v1.2.1

接下来,我们使用一开始hotfix_1.1.x_tt1的哈希码来进行搜索下:

git tag --contains 96d60ae7

image-20260318142036798

至此你就能够搜到原始1.1.x版本涉及到代码的所有tag了,后续我们就可以直接进行删包处理即可,能够精准定位所有的tag包。


三、知识点补齐

核心概念:Cherry-pick vs Merge的本质区别

在使用Git进行跨分支代码同步时,我们需要理解两种操作的本质区别:

操作方式 commit关系 追溯能力 适用场景
Cherry-pick 产生新commit,与原commit无关联 ❌ 无法通过原commit追溯 临时修复、一次性同步
Merge 保留commit关联关系 ✅ 可通过原commit追溯 长期跟踪、高危修复

重点:cherry-pick是复制代码改动,但切断历史关联;merge是合并分支,保留完整的提交父子关系。

image-20260318131228289


四、Cherry-pick & merge使用场景

何时使用Cherry-pick,其适用场景是:

  • 临时热更新:线上紧急问题,需要快速发布,不考虑长期追溯
  • 单次代码同步:只需要这次同步,后续不会再有关联修改
  • 实验性功能:不确定是否会合并回主线的功能验证

注意:使用cherry-pick时,一定要意识到它切断了历史关联,对于修改的代码就是一次新的提交记录,哈希值就会变。

何时必须使用Merge:

  • 高危代码修复:需要完整追溯影响范围的修复
  • 安全补丁:涉及安全漏洞的修复,必须能准确定位所有受影响版本
  • 长期维护分支:需要持续同步修复的分支
  • 版本发布追溯:后续可能需要删包、回滚的操作

评论区请在客户端页面查看