什么是 Git Cherry-Pick?
简单来说,git cherry-pick 的作用是 “摘取”一个或多个已有的提交,然后将它们作为一个新的提交应用到当前分支上。
你可以把它想象成从一棵树(分支)上摘下一颗或几颗特定的樱桃(提交),然后把它们挂到另一棵树上。这个过程不会移动原来的樱桃,而是创建了一份副本。
核心概念: 它应用的是 提交引入的更改,而不是直接移动提交本身。
为什么需要使用 Cherry-Pick?
git cherry-pick 的典型使用场景包括:
- 1. 修复漏洞的“神兵利器”:
- • 场景:你在 master 分支上修复了一个紧急漏洞,并进行了提交。但目前,这个漏洞在还在开发的 develop 分支和已经发布的 v1.0 分支上也存在。
- • 解决:你切换到 develop 和 v1.0 分支,然后使用 cherry-pick 将修复漏洞的那个提交单独“摘”过来应用,而无需合并整个 master 分支。
- 2. 不小心在错误的分支上提交了代码:
- • 场景:你本应在 feature/login 分支上开发,却不小心在 develop 分支上提交了几个文件。
- • 解决:
- • 在 develop 分支上,使用 git log 找到错误提交的哈希值。
- • 切换到正确的 feature/login 分支。
- • 执行 git cherry-pick <提交哈希>,将这次提交应用到 feature/login 分支。
- • 回到 develop 分支,使用 git reset 回退掉那个错误的提交。
- 3. 只想应用某个功能的一部分提交:
- • 场景:一个功能分支 feature/A 有10个提交,但你只想将其中的第3、第7个提交引入到主分支,由于它们包含了一些可复用的组件或修复。
- • 解决:在主分支上,直接 cherry-pick 那两次特定的提交。
- 4. 移植特定提交:在不同但具有类似代码库的项目间移植某个特定的补丁或功能。
基本语法与用法
1. 摘取单个提交
git cherry-pick <commit-hash>
- • <commit-hash> 是你想要摘取的提交的哈希值,一般取前7位即可(如 a1b2c3d)。
示例:
假设我们想将提交 a1b2c3d 应用到当前分支。
# 1. 第一,确保你位于目标分支上(列如 develop)
git checkout develop
# 2. 执行 cherry-pick
git cherry-pick a1b2c3d
执行成功后,Git 会在 develop 分支上创建一个新的提交,这个新提交引入的更改与 a1b2c3d 完全一样,但会有一个新的哈希值。
2. 摘取多个提交
你可以一次指定多个提交,它们会按提交历史的顺序被依次应用到当前分支。
# 摘取一系列连续的提交(不包含结束点,类似于 log)
git cherry-pick <start-commit-hash>^..<end-commit-hash>
# 或者摘取多个不连续的提交
git cherry-pick <commit-hash-1> <commit-hash-2> <commit-hash-3>
示例:
# 将提交 A 到 D(不包括A,包括D)之间的所有提交应用到当前分支
git cherry-pick A^..D
# 或明确指定三个不连续的提交
git cherry-pick a1b2c3d e4f5g6h i7j8k9l
3. 常用选项
- • -n / –no-commit:
- • 摘取更改,但不会自动创建提交。它会将更改放入暂存区和工作区,允许你手动修改后一次性提交。
- • 适用场景:当你需要将多个 cherry-pick 的更改合并为一个提交,或者想在提交前做些微调时。
- • git cherry-pick -n a1b2c3d
# … 修改一些东西 …
git commit -m “手动合并了cherry-pick的更改和一些调整” - • -x:
- • 在提交信息中附加一行(cherry picked from commit …),说明这个提交是从哪里摘取来的。这对于跟踪和审计超级有用。
- • 注意:一般只在公共分支(如 master, develop)上使用,在私有功能分支上没必要。
- • -s / –signoff:
- • 在提交信息的末尾添加一行 Signed-off-by: 签名。
- • -e / –edit:
- • 允许你在创建新提交前编辑提交信息。
- • –abort:
- • 当 cherry-pick 过程中发生冲突,你想撤销整个操作并回到操作前的状态。
- • # 发生冲突后…
git cherry-pick –abort - • –continue:
- • 当你手动解决了冲突后,使用此命令继续完成 cherry-pick 过程。
- • # 解决完所有冲突,并用 git add . 标记为已解决后…
git cherry-pick –continue
处理冲突
和 merge 或 rebase 一样,cherry-pick 也可能发生冲突。
处理流程:
- 1. Git 会暂停操作,并告知你哪些文件冲突了。
- 2. 手动解决冲突:用编辑器打开冲突文件,解决 <<<<<<<, =======, >>>>>>> 标记的部分。
- 3. 标记冲突已解决:使用 git add <file-path> 或 git add . 将解决后的文件加入暂存区。
- 4. 继续操作:执行 git cherry-pick –continue 来完成整个过程。
- 5. 或者放弃:如果冲突太复杂想放弃,执行 git cherry-pick –abort。
最佳实践与注意事项
- 1. 慎用原则:cherry-pick 很强劲,但不要滥用。它破坏了提交历史的线性,可能会导致历史混乱。在团队协作中,合并 一般是更被推荐的方式。
- 2. 主要用于修复漏洞:它的王牌场景就是在多个分支间 backport 或 forward-port 修复补丁。
- 3. 理解“副本”本质:记住,cherry-pick 创建的是新提交,它们和原提交除了更改内容一样外,是完全独立的。
- 4. 小心依赖关系:如果你摘取的提交依赖于之前的其他提交,可能会由于缺少依赖而引入不完整的功能或错误。确保你摘取的提交是自包含的。
总结
|
场景 |
命令示例 |
说明 |
|
应用一个修复 |
git cherry-pick a1b2c3d |
最常用,直接应用特定提交 |
|
应用多个修复 |
git cherry-pick A^..C |
将A之后到C的提交按顺序应用 |
|
应用但不提交 |
git cherry-pick -n a1b2c3d |
方便与其他修改合并后一起提交 |
|
记录来源 |
git cherry-pick -x a1b2c3d |
在信息中记录原提交,便于追溯 |
|
解决冲突后继续 |
git cherry-pick –continue |
标准冲突解决流程 |
|
放弃操作 |
git cherry-pick –abort |
冲突太复杂时回退到操作前状态 |
希望这份详细的讲解能协助你成为 git cherry-pick 的使用专家!它是一个在特定场景下能极大提升效率的工具,但务必牢记“能力越大,责任越大”。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...