Git Cherry-pick:核心命令、实践详解
一、Cherry-pick
1. 简介
在多分支协作开发中,我们常常只想把某个分支上的单个或若干次提交,合并到另一个分支,而不需要合并整个分支。Git 提供的 cherry-pick 命令,正是为此而生的利器。
掌握 cherry-pick 如同获得代码移植手术刀,合理使用能让你的版本控制更加优雅高效!🎯
2. 核心目的
git cherry-pick 的核心目的:将指定提交(commit)复制到另一个分支,形成一个全新的提交。在多人协作或多分支开发时,难免出现以下场景:
- 某个修复或新功能在 dev 分支上完成,但紧急想把它合并到 master 分支上单独发布。
- 不想合并整个分支,只想把分支中"部分有用提交"挑选出来到另一个分支。
此时 cherry-pick 可以轻松解决问题。记住一点:在目标分支上,Cherry-pick 生成的是新的 commit,其哈希值会与原分支不同。
二、基本用法
plain
$ git cherry-pick <commitHash>
- <commitHash> 通常指要复制的提交的哈希值,也可以是分支名(代表分支最新的那次提交)。
- 执行后,当前分支会产生一个新的提交,内容和被复制的提交相同,但哈希值不同。
1. 基本命令以及用法
操作 | 命令示例 | 说明 |
---|---|---|
将单个提交应用到当前分支 | git cherry-pick <commitHash> | 将 <commitHash> 对应的提交复制到当前分支,产生一个新的提交(新的哈希值)。 |
将某分支最新提交复制过来 | git cherry-pick <branchName> | 例如 git cherry-pick feature 表示复制 feature 分支中"最近一次提交"到当前分支。 |
一次性复制多个提交 | git cherry-pick <HashA> <HashB> | 将多个提交依次应用到当前分支,生成多个新的提交。 |
复制一段连续提交 | git cherry-pick A...B | 复制从 A(不含)到 B(含)的所有提交到当前分支;如果要包含 A,也可用 A^...B。 |
跨仓库复制提交 | 1. git remote add target <gitUrl> 2. git fetch target 3. git cherry-pick <commitHash> | 先添加远程仓库并 fetch,拿到远程分支的提交后,通过 cherry-pick 复制到本地当前分支。 |
2. 示例:
假设当前有两个分支:master 和 feature,feature 分支中有一个提交 Hash 为 f。我们想要把 f 提交应用到 master 分支。
- 切换到 master 分支:
git
git checkout master
- 在 master 分支上执行 Cherry-pick:
git
git cherry-pick f
这样就把提交 f 整合到了 master 分支上,会生成一个新的哈希。
如果要转移的是 feature 分支最近一次的提交,也可以直接:
git
git cherry-pick feature
三、一次性转移多个提交
Cherry-pick 可以一次性转移多个提交,使用方法也很灵活。
1. 显式列出多个 Hash:
plain
git cherry-pick <HashA> <HashB>
将 HashA 和 HashB 这两个提交依次应用到当前分支,形成两个新提交。
2. 转移一段连续的提交:
plain
git cherry-pick A..B
- 该命令会转移从 A(不含)到 B(含)这段提交。
- 注意:A 必须在时间线(提交历史)上早于 B,否则会出错或得到意料外的结果。
- 如果需要包含 A 本身,也可以使用 A^...B。
使用连续区间的方式,能减少命令行输入,适合你要一次性转移多个连续的提交。
四、常用配置项
Cherry-pick 有一些常用的参数,可以增强在实际项目中的灵活性。
1. -e / --edit
- 打开外部编辑器,让你编辑提交信息。
- 用于在复制过来的提交信息里补充备注,或对原先的提交信息做修改。
2. -n / --no-commit
- 只更新工作区和暂存区,而不自动产生命令对应的新提交。
- 适用于你想先合并多个提交,然后再一次性手动提交。
3. -x
- 在提交信息末尾追加一行 (cherry picked from commit <原始Hash>)。
- 这行信息可帮助追溯该提交的来源,遇到问题能快速定位。
4. -s / --signoff
- 在提交信息末尾附加操作者的签名(类似 Signed-off-by: <Name> <Email>)。
- 一般用于审计或标记提交来源的人。
5. -m parent-number / --mainline parent-number
- 如果原始提交是一个合并节点(拥有多个父提交),默认情况下 Cherry-pick 会失败,因为它不知道应该采用哪个父提交的变动。
- -m 参数用来指定使用哪个父提交:
git
git cherry-pick -m 1 <commitHash>
- parent-number 从 1 开始计数:
- 1 号父提交为"接受合并的分支"(the branch being merged into),
- 2 号父提交为"提供变动的分支"(the branch being merged from)。
6. 配置项总结
参数或配置 | 命令示例 | 说明 |
---|---|---|
-e / --edit | git cherry-pick -e <commitHash> | 打开编辑器修改提交信息,适合想在提交信息里补充/修改说明的情况。 |
-n / --no-commit | git cherry-pick -n <commitHash> | 仅更新工作区和暂存区,不自动创建新提交;可将多个提交合并后再手动一次性 git commit。 |
-x | git cherry-pick -x <commitHash> | 在提交信息末尾添加 (cherry picked from commit <originalHash>),便于后续追溯该提交来源。 |
-s / --signoff | git cherry-pick -s <commitHash> | 在提交信息末尾追加 Signed-off-by 签名,标明是谁进行了 cherry-pick 操作。 |
-m / --mainline <parent-number> | git cherry-pick -m 1 <mergeCommitHash> | 如果目标提交是合并提交(有多个父提交),则用 -m 指定采用哪一个父提交; parent-number 从 1 开始计数,一般 1 为被合并分支,2 为提供合并内容的分支。 |
五、代码冲突处理
当 Cherry-pick 过程中遇到代码冲突,Git 会暂停操作,等待你手动解决冲突并指定后续流程。常见命令有:
1. --continue
- 先解决完冲突(编辑冲突文件),然后 git add . 把修改添加到暂存区,最后执行:
git
git cherry-pick --continue
- 让 Cherry-pick 继续执行剩余的操作。
2. --abort
- 放弃这次 Cherry-pick:
plain
git cherry-pick --abort
- 回到 Cherry-pick 操作前的分支状态,仿佛什么都没发生过。
3. --quit
- 退出 Cherry-pick,但不恢复到操作之前的状态,保留已经合并到工作区和暂存区的修改。
- 通常很少使用,除非你想手动控制后续所有操作。
4. 冲突处理总结
操作 | 命令示例 | 说明 |
---|---|---|
继续 | git cherry-pick --continue | 先解决冲突并将文件 git add 至暂存区后,再执行本命令继续 Cherry-pick 剩余操作。 |
放弃 | git cherry-pick --abort | 放弃这次操作,工作区回到 cherry-pick 前的状态,仿佛未曾进行过 cherry-pick。 |
退出 | git cherry-pick --quit | 退出 cherry-pick,不恢复到操作前的状态,已合并到工作区或暂存区的修改会保留。一般少用,除非你想手动处理后续所有事情。 |
六、跨代码库的 Cherry-pick
Cherry-pick 还能将另一个远程代码库的提交,转移到本地仓库。具体步骤如下:
1. 添加远程仓库
git
git remote add target git://gitUrl
2. 抓取远程内容
git
git fetch target
3. 查看要 Cherry-pick 的提交哈希
git
git log target/master
4. 执行 Cherry-pick
git
git cherry-pick <commitHash>
这样就把远程仓库 target 某个分支上的提交复制到你的本地当前分支。
七、Demo
假设想把 dev 分支上某次提交(哈希值为 f99f2b57)移到 master 分支:
1. 切换到 master:
plain
git checkout master
2. Cherry-pick:
plain
git cherry-pick f99f2b57b7ee72d55a08e699fbeec34cbac96cb8
3. 推送到远程 master:
plain
git push origin master
注意:Cherry-pick 会生成一个新的 commit id。若此后你想要让 dev 再次合并到 master,通常需要先在 dev 上执行 rebase 以避免重复或冲突。
八、总结
- 使用场景
- Cherry-pick:只需引入某几个提交,常用于补丁、紧急修复或"选取部分功能"。
- Merge/Rebase:需整合整个分支的提交,确保功能完整对齐。
- 注意事项
- Cherry-pick 会产生新的 commit id,与原分支提交不同;后续若要整体合并分支,需小心重复提交或冲突。
- 若操作前已在公共远程仓库同步,Rebase 或重写历史要谨慎,以免影响他人。
- 最佳实践
- 在提交信息中使用 -x 等方式记录来源 commit,便于后续排查。
- 需要多次 Cherry-pick 时,可先用 -n 累积修改,然后一次性提交,避免产生大量碎提交。
- 团队协作要约定好何时使用 Merge、何时使用 Rebase、何时使用 Cherry-pick,保证历史清晰可维护。