IDEA和GIT实现cherry pick拣选部分变更到新分支
前言
在工作中,当你出现一些情况,需要将一个分支的部分变动提取出来,只需要更新提取出来的情况就需要用到当前文章提到的git的功能
并且正常情况下,你工作是没有权限直接合并到生产分支,并且前一个需求还没合并到生产分支,如果你想要复用这部分的改动逻辑,那么就需要用到这个操作,也叫cherry-pick拣选
核心作用
核心作用是将一个或多个已有的提交(commit)复制到当前所在的分支上。你可以把它想象成在一棵果树上,只挑选(pick)几颗你想要的,而不是把整根树枝都搬过来。
为什么需要它?
主要用于那些不需要合并整个分支,而只需要其中几个特定提交的情况。将修复补丁应用到多个分支这是最常见、最经典的场景。假设你有一个bugfix分支上修复了一个关键 bug,这个提交的 hash 是 a1b2c3d。现在你需要将这个修复同时应用到:
main 分支(生产环境)
develop 分支(开发环境)
可能还有旧的维护分支 v1.x
你不需要将整个 bugfix 分支合并到这些分支上,只需要在每个目标分支上执行:
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方式会比较方便操作基本语法实例
# 切换到目标分支git checkout main # 拣选单个提交git cherry-pick abc1234 # 拣选单个提交并保留原提交信息git cherry-pick -x abc1234 # 拣选但不立即提交(允许修改后再提交)git cherry-pick -n abc1234 一次挑选多个提交实例
挑选不连续的多个提交
# 切换到目标分支git checkout feature-branch # 一次挑选多个不连续的提交git cherry-pick commit1-hash commit2-hash commit3-hash # 实际示例git cherry-pick a1b2c3d e4f5g6h i7j8k9l 挑选连续的提交范围
# 方法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 遇到冲突时的处理步骤:
# 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. 将解决后的文件标记为已解决gitadd file.txt # 5. 继续完成cherry-pick操作git cherry-pick --continue # 6. 如果需要放弃这次cherry-pickgit cherry-pick --abort # 7. 如果冲突复杂,可以跳过当前提交git cherry-pick --skip - 冲突解决示例
假设 file.txt 内容冲突:
<<<<<<< HEAD 这是当前分支的内容 ======= 这是要拣选的提交的内容 >>>>>>> a1b2c3d... 提交信息 手动解决后:
这是合并后的新内容 然后执行:
gitadd file.txt git cherry-pick --continue 挑选某个分支的某次变更的某个文件
方法一:使用 git checkout(推荐)
# 步骤1:切换到目标分支git checkout main # 步骤2:从源分支的特定提交中检出单个文件git checkout feature-branch -- path/to/specific-file.js # 或者直接使用提交hashgit checkout a1b2c3d -- src/utils/helper.js # 步骤3:提交这个文件gitadd src/utils/helper.js git commit -m "feat: 从feature-branch的提交a1b2c3d中拣选helper.js"方法二:使用 cherry-pick + reset
# 步骤1:切换到目标分支git checkout main # 步骤2:执行cherry-pick但不提交git cherry-pick -n a1b2c3d # 步骤3:重置暂存区,保留工作区改动git reset HEAD # 步骤4:只添加需要的单个文件gitadd src/utils/helper.js # 步骤5:提交git commit -m "feat: 拣选helper.js from a1b2c3d"# 步骤6:清理不需要的改动(可选)git checkout -- .挑选某个分支的某次变更的多个文件
方法一:使用 git checkout 检出多个文件
# 步骤1:切换到目标分支git checkout main # 步骤2:检出多个特定文件git checkout feature-branch -- src/components/Button.js src/styles/theme.css src/utils/constants.js # 步骤3:提交这些文件gitadd.git commit -m "feat: 从feature-branch拣选多个UI组件文件"方法二:使用 cherry-pick + 选择性添加
# 步骤1:切换到目标分支git checkout develop # 步骤2:cherry-pick但不提交git cherry-pick -n b2c3d4e # 步骤3:重置暂存区git reset HEAD # 步骤4:查看哪些文件被修改了git status # 步骤5:选择性添加需要的多个文件gitadd src/components/Modal.js src/hooks/useModal.js # 步骤6:提交选中的文件git commit -m "feat: 拣选Modal组件及相关hook"# 步骤7:丢弃不需要的文件改动git checkout -- .方法三:创建临时分支(最安全的方法)
# 步骤1:创建临时分支git checkout -b temp-cherry-pick # 步骤2:执行完整cherry-pickgit cherry-pick c3d4e5f # 步骤3:重置到cherry-pick之前的状态,但保留文件改动git reset HEAD^ # 步骤4:检查并选择需要的文件git status # 步骤5:添加需要的多个文件gitadd 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 综合实战示例
场景:从修复分支挑选特定修复文件
# 假设在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 gitadd src/security/permissions.js src/payment/processor.js git commit -m "security: 应用关键安全修复"git checkout -- .结语
如上实现了DEA和GIT实现cherry pick拣选部分变更到新分支