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