git cherry-pick 是 Git 中一个强大的命令,它允许你选择一个或多个已存在的提交(commit),并将其应用到当前分支。这个过程会创建新的提交,而不是移动或复制原有的提交。
Cherry-pick 的核心工作原理如下:
与 merge 和 rebase 不同,cherry-pick 可以让你精确选择需要的提交,而不是合并整个分支的历史。
在以下情况下,cherry-pick 特别有用:
git cherry-pick <commit-hash>
git cherry-pick [options] <commit>...
常用选项:
<commit-hash>:要应用的提交的哈希值-e, --edit:在提交前编辑提交信息-n, --no-commit:应用变更但不自动提交-x:在提交信息中添加 “(cherry picked from commit …)” 注释-m parent-number:指定主线父提交(用于 merge commit)--continue:解决冲突后继续 cherry-pick 过程--abort:取消 cherry-pick 操作并恢复到之前的状态--quit:退出 cherry-pick 但保留已经成功的提交# 1. 查看提交历史,找到要 cherry-pick 的提交
git log --oneline
# 2. 切换到目标分支
git checkout target-branch
# 3. 执行 cherry-pick
git cherry-pick abc1234
# 4. 验证结果
git log
问题描述:
你在 develop 分支上修复了一个严重的 bug,但 main 和 release-v1.0 分支也存在同样的问题,需要快速修复。
解决方案:
# 在 develop 分支修复 bug 并提交
git checkout develop
# ... 修复代码 ...
git add .
git commit -m "fix: 修复用户登录时的空指针异常"
# 记录此次提交的哈希值,假设为 a1b2c3d
# 应用到 main 分支
git checkout main
git cherry-pick a1b2c3d
git push origin main
# 应用到 release 分支
git checkout release-v1.0
git cherry-pick a1b2c3d
git push origin release-v1.0
优点:
问题描述:
你的团队在 feature/new-dashboard 分支上开发了多个功能,但只有”用户统计图表”这个功能需要在下个版本发布,其他功能还需要更多测试。
解决方案:
# 1. 找到实现用户统计图表的相关提交
git checkout feature/new-dashboard
git log --oneline --grep="用户统计"
# 假设找到以下提交:
# b2c3d4e feat: 添加用户统计图表组件
# c3d4e5f feat: 实现用户统计数据 API
# d4e5f6g style: 优化统计图表样式
# 2. 切换到发布分支并依次应用
git checkout release/v2.0
git cherry-pick c3d4e5f # 先应用 API
git cherry-pick b2c3d4e # 再应用组件
git cherry-pick d4e5f6g # 最后应用样式
# 3. 测试并推送
# ... 进行测试 ...
git push origin release/v2.0
注意事项:
问题描述:
你本应该在 feature/user-profile 分支上提交代码,但不小心提交到了 develop 分支。
解决方案:
# 1. 记录错误提交的哈希值
git checkout develop
git log --oneline -1
# 假设错误提交的哈希值为 e5f6g7h
# 2. 切换到正确的分支并应用提交
git checkout feature/user-profile
git cherry-pick e5f6g7h
# 3. 从 develop 分支移除错误提交
git checkout develop
git reset --hard HEAD~1
# 或者使用 revert(如果已经推送到远程)
# git revert e5f6g7h
# 4. 推送更改(如果已推送到远程,需要强制推送)
# 注意:强制推送需要团队协调,确保不影响其他人
git push origin develop --force-with-lease
安全建议:
git revert 而不是 reset--force-with-lease 而不是 --force,更安全问题描述:
需要将 feature/payment 分支上的一系列支付相关提交应用到 hotfix 分支。
解决方案:
# 1. 查看要挑选的提交范围
git checkout feature/payment
git log --oneline
# 假设提交历史如下:
# f6g7h8i feat: 添加支付宝支付
# g7h8i9j feat: 添加微信支付
# h8i9j0k feat: 统一支付接口
# i9j0k1l refactor: 优化支付流程
# 2. 使用范围语法 cherry-pick 连续提交(包含第一个,包含最后一个)
git checkout hotfix
git cherry-pick h8i9j0k^..f6g7h8i
# 或者使用
git cherry-pick f6g7h8i~3..f6g7h8i
# 3. 验证所有提交都已应用
git log --oneline -4
问题描述:
你想应用另一个分支的提交,但需要修改提交信息以符合当前分支的提交规范。
解决方案:
# 使用 -e 或 --edit 选项
git cherry-pick -e j0k1l2m
# 这会打开编辑器,允许你修改提交信息
# 修改后保存即可
# 或者,应用变更但不自动提交,然后手动提交
git cherry-pick -n j0k1l2m
git status
# 检查变更内容
git commit -m "feat: 根据新规范重写的提交信息"
# 挑选单个提交
git cherry-pick <commit-hash>
# 挑选多个不连续的提交
git cherry-pick <commit-1> <commit-2> <commit-3>
# 挑选一系列连续的提交
git cherry-pick <start-commit>^..<end-commit>
# 或
git cherry-pick <start-commit>~n..<end-commit>
# 或
git cherry-pick <start-commit>..<end-commit> # 不包含 start-commit
# 应用提交但不自动提交(可以修改后再提交)
git cherry-pick -n <commit-hash>
git cherry-pick --no-commit <commit-hash>
# 挑选时编辑提交信息
git cherry-pick -e <commit-hash>
git cherry-pick --edit <commit-hash>
# 在提交信息中添加 cherry-pick 来源记录
git cherry-pick -x <commit-hash>
# 仅保留变更,不保留原提交信息
git cherry-pick --no-commit <commit-hash>
git commit -m "新的提交信息"
# 当 cherry-pick 发生冲突时
# 1. 查看冲突文件
git status
# 2. 手动解决冲突
# 编辑冲突文件,解决冲突标记
# 3. 标记冲突已解决
git add <resolved-files>
# 4. 继续 cherry-pick 过程
git cherry-pick --continue
# 或者,跳过当前提交
git cherry-pick --skip
# 或者,放弃整个 cherry-pick 操作
git cherry-pick --abort
# 退出 cherry-pick 但保留已成功的提交
git cherry-pick --quit
# 方法 1:使用提交范围
git cherry-pick commit-A..commit-B
# 方法 2:使用多个提交哈希
git cherry-pick commit-1 commit-2 commit-3
# 方法 3:从另一个分支挑选所有提交(不推荐,考虑用 merge)
git cherry-pick develop~10..develop
# 方法 4:使用循环批量处理
for commit in commit-1 commit-2 commit-3; do
git cherry-pick "$commit" || break
done
# 方法 5:从文件读取提交列表
cat commits.txt | xargs git cherry-pick
# 撤销最近一次 cherry-pick(提交前)
git cherry-pick --abort
# 撤销已完成的 cherry-pick
git reset --hard HEAD~1 # 删除最后一次提交
# 或使用 revert(推荐,特别是已推送到远程时)
git revert HEAD
# 撤销多个 cherry-pick
git reset --hard HEAD~3 # 撤销最近 3 次提交
# 查看 cherry-pick 历史(使用 reflog)
git reflog
# 恢复到某个历史状态
git reset --hard HEAD@{5}
# Cherry-pick 合并提交(merge commit)
# -m 1 表示选择第一个父提交作为主线
git cherry-pick -m 1 <merge-commit-hash>
# Cherry-pick 时保持原作者信息
git cherry-pick --author="Original Author <email@example.com>" <commit-hash>
# Cherry-pick 并自动解决策略冲突(使用我们的版本,当前分支)
git cherry-pick -X ours <commit-hash>
# Cherry-pick 并自动解决策略冲突(使用他们的版本,被pick的分支)
git cherry-pick -X theirs <commit-hash>
# 显示 cherry-pick 过程的详细信息
git cherry-pick --verbose <commit-hash>
# Cherry-pick 时使用不同的合并策略
git cherry-pick --strategy=recursive -X patience <commit-hash>
# 查看哪些提交可以被 cherry-pick
git log <source-branch> --not <target-branch> --oneline
# 检查提交是否已经被 cherry-pick 过
git log --all --grep="<commit-message>"
# 查看两个分支之间的差异提交
git log target-branch..source-branch --oneline
# 以图形方式查看提交历史
git log --graph --oneline --all
# 查看特定提交的详细信息
git show <commit-hash>
# 查看 cherry-pick 状态(如果在进行中)
cat .git/CHERRY_PICK_HEAD
-x 选项追踪来源git cherry-pick -x <commit-hash>
这会在提交信息中添加 (cherry picked from commit ...) 注释,方便后续追踪变更来源。
确保要 cherry-pick 的提交是:
Cherry-pick 不应是首选方案,以下情况考虑其他选项:
git mergegit rebase# Cherry-pick 后进行充分测试
git cherry-pick <commit-hash>
# 运行测试
npm test # 或其他测试命令
# 确认无误后推送
git push origin <branch-name>
遇到冲突时,尽快解决以避免影响其他工作:
# 解决冲突后
git add .
git cherry-pick --continue
Cherry-pick 会创建新的提交哈希,可能导致:
解决方案:
git log 和 git diff 检查是否已有相同变更Cherry-pick 单个提交可能遗漏依赖:
# 错误示例:只 cherry-pick 使用新函数的提交
git cherry-pick abc123 # 使用了 newFunction()
# 正确做法:同时 cherry-pick 定义和使用
git cherry-pick def456 # 定义 newFunction()
git cherry-pick abc123 # 使用 newFunction()
对于 merge commit,必须指定主线:
# 查看 merge commit 的父提交
git show <merge-commit-hash>
# 指定第一个父提交为主线
git cherry-pick -m 1 <merge-commit-hash>
如果需要修改已推送的历史,使用 --force-with-lease 而不是 --force:
# 更安全的强制推送
git push origin branch-name --force-with-lease
Cherry-pick 二进制文件时冲突难以解决,建议:
--ours / --theirs 策略# 发生冲突时选择当前分支的版本
git checkout --ours <binary-file>
git add <binary-file>
git cherry-pick --continue
大量提交的 cherry-pick 可能很慢:
# 不推荐:cherry-pick 大量提交
git cherry-pick commit-1..commit-100
# 推荐:考虑使用 rebase 或 merge
git rebase --onto target-branch commit-1 commit-100
保持提交信息的一致性和可追溯性:
# 添加 cherry-pick 来源信息
git cherry-pick -x <commit-hash>
# 或在提交信息中手动注明
git cherry-pick -e <commit-hash>
# 编辑信息,添加类似:
# Cherry-picked from branch feature/xxx for hotfix
当遇到 cherry-pick 冲突时,按以下步骤处理:
git status
git diff
<<<<<<<, =======, >>>>>>>)# 继续
git add .
git cherry-pick --continue
# 或中止
git cherry-pick --abort
git cherry-pick 是一个强大而灵活的工具,适合精确控制提交的应用场景。正确使用它可以:
但也要注意:
掌握 cherry-pick 的正确用法,能够让你的 Git 工作流更加高效和灵活!