什么是cherry-pick?

cherry-pick是一个强大的Git命令,用于将一个或多个其他分支的提交应用到当前分支。这个命令让你能够选择性地拾取某个分支上的提交(即”樱桃挑选”或"拣选"),而不是通过合并或重置操作引入整个分支的更改

git 中的cherry-pick类似于对特定的某次提交的变基。 它会提取该提交的补丁,之后尝试将其重新应用到当前分支上。

使用场景

  • 当你想将一个特定的修复从一个分支(如main)应用到另一个分支(如发布分支)时,而不需要引入中间的所有提交

  • 在处理大型项目时,如果只需要某个分支上的一个小更改不是整个分支的合并

  • 在回滚特定的提交时,可以用于将该提交的反向更改应用到当前分支上。

基本用法

pick单个提交

假设我们有如下的提交历史:

1
2
3
4
5
6
7
8
MINGW64 /d/tmp/git-playground (ruby_client)
$ git log --all --oneline --graph
* 43cd18a (HEAD -> ruby_client) 5ddae
* 9f671cd e43a6
| * c0bdf4c (master) f42c5
|/
* 0fa9f4c a6b4c
* 513c20b 0b743

image-20240415162356204

image-20240415162409086

如果你希望将提交e43a6 拉取到 master 分支,你可以运行如下命令:

首先查看该次提交的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git show 9f671cd
commit 9f671cd9bf8c7fbae4a11a63fae89c32b401523b
Author: TerryLikesCoding <18328621355@163.com>
Date: Mon Apr 15 16:20:46 2024 +0800

e43a6

diff --git a/index.html b/index.html
index e69de29..793f0b4 100644
--- a/index.html
+++ b/index.html
@@ -0,0 +1 @@
+<!DOCTYPE>

此次的改动内容:往index.html文件中添加了一行<!DOCTYPE>,然后切换到master分支,执行如下命令:

1
2
3
4
5
6
7
8
9
10
11
MINGW64 /d/tmp/git-playground (ruby_client)
$ git checkout master
Switched to branch 'master'

$ cat index.html
# cherry-pick前内容为空

$ git cherry-pick 9f671cd
[master b9951e5] e43a6
Date: Mon Apr 15 16:20:46 2024 +0800
1 file changed, 1 insertion(+)

执行完成cherry-pick后,查看仓库的状态:

1
2
3
MINGW64 /d/tmp/git-playground (master)
$ cat index.html
<!DOCTYPE>

提交e43a6的变动内容已经合并到master分支,此时查看git log:

1
2
3
4
5
6
7
8
9
 MINGW64 /d/tmp/git-playground (master)
$ git log --all --oneline --graph
* b9951e5 (HEAD -> master) e43a6
* c0bdf4c f42c5
| * 43cd18a (ruby_client) 5ddae
| * 9f671cd e43a6
|/
* 0fa9f4c a6b4c
* 513c20b 0b743

image-20240415163342779

这样会拉取和 e43a6 相同的更改,但是因为应用的日期不同,你会得到一个新的提交 SHA-1 值。现在你的历史会变成这样:

image-20240415163532390

pick多个提交

  • 多个提交:可以连续列出多个提交哈希值,也可以使用范围操作符,如git cherry-pick startHash^..endHash,这将拾取从startHashendHash之间的所有提交(包括endHash,但不包括startHash)。

注意事项

  • 冲突git cherry-pick可能会引起冲突,就像合并操作一样。如果发生冲突,Git会停止应用提交,让你解决冲突。解决后,你需要使用git cherry-pick --continue来继续应用提交。

  • 选择性地引入更改:虽然cherry-pick提供了高度的选择性,但它也可能导致分支历史混乱,尤其是当被拾取的提交依赖于其他未被拾取的更改时。