Skip to content

Cherry-pick

git cherry-pick 允许你将某个分支上的特定提交应用到当前分支,而不需要合并整个分支。这在需要将某个 bug 修复从一个分支移植到另一个分支时特别有用。

git cherry-pick 基本用法

bash
# 将指定提交应用到当前分支
git cherry-pick abc123

# cherry-pick 会在当前分支创建一个新的提交(内容相同,但 SHA-1 不同)
git log --oneline
# def456 (HEAD) feat: 添加用户头像(cherry-pick from feature)
# ...

cherry-pick 的效果:

feature: A ← B ← C  ← D (C 是要 cherry-pick 的提交)
main:    A ← E ← F

git cherry-pick C:
main:    A ← E ← F ← C'  (C' 与 C 内容相同,但 SHA-1 不同)

挑选多个提交

bash
# cherry-pick 多个独立提交(按顺序应用)
git cherry-pick abc123 def456 ghi789

# 上面的顺序很重要,Git 会依次应用

挑选范围提交

bash
# 挑选 abc123(不含)到 ghi789(含)之间的所有提交
git cherry-pick abc123..ghi789

# 挑选包含 abc123 在内的范围
git cherry-pick abc123^..ghi789

注意范围的顺序: 从旧到新,否则 cherry-pick 可能失败或产生错误结果。

--no-commit 模式

--no-commit(或 -n)应用提交的改动但不自动创建提交:

bash
# 应用改动到暂存区,不自动提交
git cherry-pick --no-commit abc123
git cherry-pick -n abc123

# 可以查看改动,做进一步调整
git status
git diff --cached

# 满意后手动提交
git commit -m "feat: 移植登录功能修复(from feature/login)"

# 或者将多个 cherry-pick 合并为一次提交
git cherry-pick --no-commit abc123 def456 ghi789
git commit -m "fix: 移植多个 bug 修复到 hotfix 分支"

冲突处理

cherry-pick 过程中也可能遇到冲突:

bash
# cherry-pick 遇到冲突时:
# error: could not apply abc123... feat: 添加登录功能
# hint: After resolving the conflicts, mark them with
# hint: "git add/rm <pathspec>", then run "git cherry-pick --continue"

# 1. 手动解决冲突
vim src/auth.js  # 编辑冲突文件

# 2. 标记冲突已解决
git add src/auth.js

# 3. 继续 cherry-pick
git cherry-pick --continue

# 放弃 cherry-pick
git cherry-pick --abort

# 跳过当前冲突的提交(谨慎!)
git cherry-pick --skip

使用场景与最佳实践

场景1:将 hotfix 从 main 移植到 develop

bash
# 在 main 分支修复了紧急 bug
git switch main
git log --oneline -5
# abc123 fix: 修复用户无法登录的问题  ← 要移植到 develop

# 切换到 develop 并 cherry-pick
git switch develop
git cherry-pick abc123

# 推送
git push

场景2:从错误分支恢复提交

bash
# 发现提交到了错误的分支
git switch wrong-branch
git log --oneline
# abc123 feat: 新功能(应该在 feature/new 分支上)

# 切换到正确分支并 cherry-pick
git switch feature/new
git cherry-pick abc123

# 删除错误分支上的提交
git switch wrong-branch
git reset --hard HEAD~1  # 移除错误提交

场景3:只需要某分支的部分提交

bash
# feature 分支有多个提交,只需要其中某些
git log feature/experimental --oneline
# abc123 feat: 功能A(想要)
# def456 feat: 功能B(不想要)
# ghi789 feat: 功能C(想要)

git switch main
git cherry-pick abc123 ghi789  # 只挑选需要的提交

场景4:测试某个提交是否解决了问题

bash
# 不切换分支,只把某个提交带过来测试
git cherry-pick --no-commit fix/abc123
# 测试...
# 如果不需要保留,取消暂存
git restore --staged .
git restore .

cherry-pick 的注意事项

1. 相同改动会有不同 SHA-1

cherry-pick 创建的是新提交,内容相同但 SHA-1 不同。如果这两个分支后来合并,Git 可能会将两个内容相同的提交都保留,造成重复。

2. 依赖关系

如果提交 B 依赖于提交 A 的改动,你只 cherry-pick B 可能会产生冲突或错误。应该同时 cherry-pick A 和 B。

3. 历史清晰性

大量使用 cherry-pick 会让历史变得难以追踪。如果经常需要在分支间同步代码,考虑使用 merge 或 rebase。

cherry-pick vs merge vs rebase

操作特点使用场景
merge合并整个分支合并功能分支到主线
rebase重新应用一系列提交整理功能分支历史
cherry-pick挑选特定提交跨分支移植特定改动

总结

操作命令
cherry-pick 单个提交git cherry-pick <sha>
cherry-pick 多个提交git cherry-pick <sha1> <sha2>
cherry-pick 范围git cherry-pick <old>..<new>
不自动提交git cherry-pick -n <sha>
继续(解决冲突后)git cherry-pick --continue
放弃git cherry-pick --abort

Cherry-pick 是一个精准的工具,适合在特定场景下使用。理解它的工作原理,能让你在复杂的分支情况下更灵活地管理代码。