Git Cherry-Pick
git cherry-pick 的用法:选择性应用提交、冲突处理、范围选择。
#type / howto
#status / growing
#tech / ops
#resource / git
[!info] related notes
- 所属 MOC: Git MOC
- 相关概念: Git中的merge和rebase, Git Rebase
- 相关流程: Git 协作流程
Git Cherry-Pick
一句话定义
cherry-pick 从其他分支”摘取”指定提交,应用到当前分支。
适用场景
- 热修复:bug 修复在 develop 分支,需要同步到 production
- 选择性合并:只需要某个分支的部分提交,不要整个分支
- 版本回溯:把某个历史提交应用到当前版本
- 误提交修复:提交到了错误分支,需要转移到正确分支
基本用法
# 应用单个提交到当前分支
git cherry-pick abc1234
# 应用多个提交
git cherry-pick abc1234 def5678 ghi9012
# 应用但不自动提交(只暂存更改)
git cherry-pick --no-commit abc1234
范围选择
# 选择一个范围的提交(不包含起始点)
git cherry-pick abc1234..ghi9012
# 选择一个范围的提交(包含起始点)
git cherry-pick abc1234^..ghi9012
# 选择最近 3 个提交
git cherry-pick HEAD~3..HEAD
冲突处理
# cherry-pick 遇到冲突
git cherry-pick abc1234
# CONFLICT (content): Merge conflict in src/app.js
# 1. 解决冲突
# 编辑 src/app.js,解决冲突标记
# 2. 标记冲突已解决
git add src/app.js
# 3. 继续 cherry-pick
git cherry-pick --continue
# 4. 放弃整个 cherry-pick
git cherry-pick --abort
# 5. 跳过当前提交
git cherry-pick --skip
实战:热修复同步
# 场景:在 develop 上修复了一个 bug,需要同步到 production
# 1. 找到修复提交
git log develop --oneline
# abc1234 fix: 修复用户登录超时问题
# 2. 切换到 production 分支
git checkout production
# 3. cherry-pick 修复提交
git cherry-pick abc1234
# 4. 如果有冲突,解决后 continue
实战:误提交纠正
# 场景:提交到了 main,应该在 feature 分支
# 1. 记下提交哈希
git log main --oneline -1
# abc1234 feat: 新功能(不应该在 main)
# 2. 从 main 撤销这个提交(保留更改)
git reset HEAD~1
# 3. 切换到 feature 分支
git checkout feature
# 4. cherry-pick 这个提交
git cherry-pick abc1234
# 5. 回到 main 确认干净
git checkout main
git status
cherry-pick vs rebase vs merge
| 操作 | 作用 | 适用场景 |
|---|---|---|
| cherry-pick | 复制特定提交 | 只需要部分提交 |
| rebase | 移植整个分支 | 同步主分支、整理历史 |
| merge | 合并分支 | 合并功能分支到主分支 |
高级选项
# 保留原始作者信息
git cherry-pick -x abc1234 # 提交信息会添加 (cherry picked from ...)
# 使用签名
git cherry-pick -S abc1234
# 自定义提交信息
git cherry-pick --no-commit abc1234
git commit -m "自定义的提交信息"
# 从另一个仓库 cherry-pick
git remote add other-repo <url>
git fetch other-repo
git cherry-pick abc1234
常见误区
- cherry-pick 创建新提交:哈希和原提交不同,不是同一个提交
- 不要频繁 cherry-pick:会导致提交历史混乱,考虑用 merge 或 rebase
- 冲突和 merge 一样:解决方式相同,但继续命令是
--continue不是--merge --no-commit不会创建提交:需要手动git commit