前言
在工作中,当你出现一些情况,需要将一个分支的部分变动提取出来,只需要更新提取出来的情况就需要用到当前文章提到的git的功能
并且正常情况下,你工作是没有权限直接合并到生产分支,并且前一个需求还没合并到生产分支,如果你想要复用这部分的改动逻辑,那么就需要用到这个操作,也叫
cherry-pick
拣选
核心作用
核心作用
是将一个或多个已有的提交(commit)复制到当前所在的分支上。
你可以把它想象成在一棵果树上,只挑选(pick)几颗你想要的,而不是把整根树枝都搬过来。
为什么需要它?
主要用于那些
不需要合并整个分支,而只需要其中几个特定提交
的情况。
将修复补丁应用到多个分支
这是最常见、最经典的场景。假设你有一个bugfix
分支上修复了一个关键 bug,这个提交的 hash
是 a1b2c3d。现在你需要将这个修复同时应用到:
main 分支(生产环境)
develop 分支(开发环境)
可能还有旧的维护分支 v1.x
你不需要将整个 bugfix 分支合并到这些分支上,只需要在每个目标分支上执行:
bash
git cherry-pick a1b2c3d
意外在错误的分支上进行了提交
你本来应该在 feature/login 分支上开发,但不小心在 main
分支上提交了代码。这时你可以:
在 feature/login 分支上,通过 git cherry-pick 将那个误提交"拿"过来。
回到 main 分支,用 git reset 撤销那个提交。
只想引入另一个分支上的某个特定功能
同事在 feature/A 分支上开发了 5 个新功能,但你目前只需要其中的第 3 个功能。你可以找到实现第 3 个功能的提交,然后用 cherry-pick 将其单独引入你的分支。
步骤
那么接下来我会列举下git操作和IDEA操作的方式,不过重点会讲IDEA操作的方式
IDEA方式
首先,我们先
新建
一个分支
在IDEA
切换该分支
在右下角,输入自己的分支,点击分支切换check out


GIT菜单栏
检索Show Git Log
或者左下角点击Git面板

这里有三部分,在中间部分有
【输入框】
可以筛选提交hash,分支名,提交文本筛选git历史记录
【Branch:All】
根据分支筛选git提交记录,默认带出所有
【User:All】
根据提交用户筛选git提交记录,默认带出所有
【Date:All】
根据提交时间筛选git提交记录,默认带出所有
【Path:All】
根据文件筛选git提交记录,默认带出所有
在这里筛选你需要拣选的分支,筛选之后,点击选中,右侧部分会带出本次git提交记录的变更文件记录

按照
ctrl
键,选中需要拣选的文件,然后在选中的文件右键选择Cherry-pick Selected Changes

然后会弹窗,加入到一个变更的列表
Name
需要加入的变更列表,可以自定义命名
Comment
提交文本

然后点击
OK
,在我们的左侧Commit
就会多出拣选的文件,然后我们正常git push 提交即可

GIT方式
git方式是比较通用的,哪怕脱离图形化工具我们也可以根据git命令执行拣选,但是按照我如下的
IDEA方式
会比较方便操作
基本语法实例
bash
# 切换到目标分支
git checkout main
# 拣选单个提交
git cherry-pick abc1234
# 拣选单个提交并保留原提交信息
git cherry-pick -x abc1234
# 拣选但不立即提交(允许修改后再提交)
git cherry-pick -n abc1234
一次挑选多个提交实例
挑选不连续的多个提交
bash
# 切换到目标分支
git checkout feature-branch
# 一次挑选多个不连续的提交
git cherry-pick commit1-hash commit2-hash commit3-hash
# 实际示例
git cherry-pick a1b2c3d e4f5g6h i7j8k9l
挑选连续的提交范围
bash
# 方法1:使用范围语法(包含start-commit,不包含end-commit)
git cherry-pick start-commit^..end-commit
# 方法2:使用..语法
git cherry-pick older-commit..newer-commit
# 实际示例 - 拣选从提交A到提交D的所有提交
git cherry-pick a1b2c3d^..d4e5f6g
# 或者明确指定范围
git cherry-pick a1b2c3d..b2c3d4e..c3d4e5f..d4e5f6g
解决冲突的完整流程
当 cherry-pick 遇到冲突时的处理步骤:
bash
# 1. 执行cherry-pick时遇到冲突
git cherry-pick a1b2c3d
# 输出:CONFLICT (content): Merge conflict in file.txt
# 输出:Automatic cherry-pick failed.
# 2. 查看冲突状态
git status
# 输出:Unmerged paths:
# 输出: both modified: file.txt
# 3. 手动解决冲突
# 编辑冲突文件,解决 <<<<<<<, =======, >>>>>>> 标记的部分
vim file.txt
# 4. 将解决后的文件标记为已解决
git add file.txt
# 5. 继续完成cherry-pick操作
git cherry-pick --continue
# 6. 如果需要放弃这次cherry-pick
git cherry-pick --abort
# 7. 如果冲突复杂,可以跳过当前提交
git cherry-pick --skip
- 冲突解决示例
假设 file.txt 内容冲突:
bash
<<<<<<< HEAD
这是当前分支的内容
=======
这是要拣选的提交的内容
>>>>>>> a1b2c3d... 提交信息
手动解决后:
bash
这是合并后的新内容
然后执行:
bash
git add file.txt
git cherry-pick --continue
挑选某个分支的某次变更的某个文件
方法一:使用 git checkout(推荐)
bash
# 步骤1:切换到目标分支
git checkout main
# 步骤2:从源分支的特定提交中检出单个文件
git checkout feature-branch -- path/to/specific-file.js
# 或者直接使用提交hash
git checkout a1b2c3d -- src/utils/helper.js
# 步骤3:提交这个文件
git add src/utils/helper.js
git commit -m "feat: 从feature-branch的提交a1b2c3d中拣选helper.js"
方法二:使用 cherry-pick + reset
bash
# 步骤1:切换到目标分支
git checkout main
# 步骤2:执行cherry-pick但不提交
git cherry-pick -n a1b2c3d
# 步骤3:重置暂存区,保留工作区改动
git reset HEAD
# 步骤4:只添加需要的单个文件
git add src/utils/helper.js
# 步骤5:提交
git commit -m "feat: 拣选helper.js from a1b2c3d"
# 步骤6:清理不需要的改动(可选)
git checkout -- .
挑选某个分支的某次变更的多个文件
方法一:使用 git checkout 检出多个文件
bash
# 步骤1:切换到目标分支
git checkout main
# 步骤2:检出多个特定文件
git checkout feature-branch -- src/components/Button.js src/styles/theme.css src/utils/constants.js
# 步骤3:提交这些文件
git add .
git commit -m "feat: 从feature-branch拣选多个UI组件文件"
方法二:使用 cherry-pick + 选择性添加
bash
# 步骤1:切换到目标分支
git checkout develop
# 步骤2:cherry-pick但不提交
git cherry-pick -n b2c3d4e
# 步骤3:重置暂存区
git reset HEAD
# 步骤4:查看哪些文件被修改了
git status
# 步骤5:选择性添加需要的多个文件
git add src/components/Modal.js src/hooks/useModal.js
# 步骤6:提交选中的文件
git commit -m "feat: 拣选Modal组件及相关hook"
# 步骤7:丢弃不需要的文件改动
git checkout -- .
方法三:创建临时分支(最安全的方法)
bash
# 步骤1:创建临时分支
git checkout -b temp-cherry-pick
# 步骤2:执行完整cherry-pick
git cherry-pick c3d4e5f
# 步骤3:重置到cherry-pick之前的状态,但保留文件改动
git reset HEAD^
# 步骤4:检查并选择需要的文件
git status
# 步骤5:添加需要的多个文件
git add src/api/user.js src/store/auth.js
# 步骤6:提交
git commit -m "feat: 拣选用户认证相关文件"
# 步骤7:回到目标分支并合并临时分支
git checkout main
git cherry-pick temp-cherry-pick
# 步骤8:删除临时分支
git branch -D temp-cherry-pick
综合实战示例
场景:从修复分支挑选特定修复文件
bash
# 假设在hotfix-branch上有多个提交,我们只需要其中的安全修复
# 查看hotfix-branch的提交历史
git log hotfix-branch --oneline -5
# 输出:
# f1e2d3c 修复支付漏洞
# e2d3c4b 更新文档
# d3c4b5a 修复安全权限
# c4b5a6b 样式调整
# b5a6b7c 功能增强
# 我们只需要安全相关的修复:d3c4b5a 和 f1e2d3c
# 方法1:逐个拣选需要的提交
git checkout main
git cherry-pick d3c4b5a
git cherry-pick f1e2d3c
# 方法2:批量拣选但只保留特定文件
git checkout main
git cherry-pick -n d3c4b5a f1e2d3c
git reset HEAD
git add src/security/permissions.js src/payment/processor.js
git commit -m "security: 应用关键安全修复"
git checkout -- .
结语
如上实现了DEA和GIT实现cherry pick拣选部分变更到新分支