git cherry-pick 使用

工作中, 我们经常会需要从其他分支获取一些重要的修改, 但只是部分commit, 不能用merge, 这时cherry-pick就派上用场了.
cherry-pick可以把其他分支的某些commit合并到当前分支, 具体使用和注意事项请看下面的实操.

cherry-pick 实操


假设有一个分支origin/niko_blog_test, 他的git log如下:


commit ceaa73fd804aefc406f6384c9c0fffaedafbcb79
Author: niko <329872193@qq.com>
Date: Wed Nov 2 14:54:39 2016 +0800

Add: txt-02.

commit 42a87088af08b54cf09be122e39e4d85c0f450ec
Author: niko <329872193@qq.com>
Date: Wed Nov 2 14:54:11 2016 +0800

Add: txt-01.

commit f000b1ac4bf9dbd57d107895f349f448a3af05cc
Author: niko <329872193@qq.com>
Date: Wed Nov 2 10:27:47 2016 +0800

hello

基于f000b1ac4bf9dbd57d107895f349f448a3af05cc的commit建立分支niko_blog_test-2:

git checkout -b niko_blog_test-2 f000b1ac4bf9dbd57d107895f349f448a3af05cc

查看git log:

commit f000b1ac4bf9dbd57d107895f349f448a3af05cc
Author: niko <329872193@qq.com>
Date: Wed Nov 2 10:27:47 2016 +0800

hello

开始cherry-pick


我们要把niko_blog_test的两个最新commit, pick到niko_blog_test-2中, 操作如下:

$ git cherry-pick ceaa73f 42a8708
error: could not apply ceaa73f... Add: txt-02.
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

提示冲突, 进行合并:

$ git mergetool

此时状态:

$ git st
On branch niko_blog_test-2
You are currently cherry-picking commit ceaa73f.
(all conflicts fixed: run "git cherry-pick --continue")
(use "git cherry-pick --abort" to cancel the cherry-pick operation)

Changes to be committed:

modified: README.txt

进行commit操作.

然后继续记性cherry-pick:

$ git cherry-pick --continue
error: could not apply 42a8708... Add: txt-01.
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

又提示冲突, 这里要手动解决了.

$ git mergetool

冲突解决后, 此时状态:

$ git st
On branch niko_blog_test-2
You are currently cherry-picking commit 42a8708.
(all conflicts fixed: run "git cherry-pick --continue")
(use "git cherry-pick --abort" to cancel the cherry-pick operation)

Changes to be committed:

modified: README.txt

进行commit操作.

git cherry-pick --continue会打印空内容, 表示cherry-pick结束.

此时再查看log:

commit e68a53fef3229c6536b44781d2cb8322aa4202e1
Author: niko <329872193@qq.com>
Date: Wed Nov 2 14:54:11 2016 +0800

Add: txt-01.

cherry-picking commit 42a8708.

Conflicts:
hsb-common/README.txt

commit 9d7a471f646742da9b68e663fee41be62a0e17b7
Author: niko <329872193@qq.com>
Date: Wed Nov 2 14:54:39 2016 +0800

Add: txt-02.

cherry-picking commit ceaa73f.

Conflicts:
hsb-common/README.txt

commit f000b1ac4bf9dbd57d107895f349f448a3af05cc
Author: niko <329872193@qq.com>
Date: Wed Nov 2 10:27:47 2016 +0800

hello

可以看到f000b1ac4bf9dbd57d107895f349f448a3af05cc之后多了两个commit, README.txt的内容也过来了.

其实, 上面的操作之所以很曲折, 是因为顺序错了, 哇哈哈哈 !!!只要按commit时间顺序来, 就不会有这么多的冲突问题, 如下所示.

cherry-pick 实操 - 按时间顺序


重来的话, 我们reset到f000b1ac4bf9dbd57d107895f349f448a3af05cc版本:

$ git reset --hard f000b1ac4bf9dbd57d107895f349f448a3af05cc
HEAD is now at f000b1a hello

$ git log
commit f000b1ac4bf9dbd57d107895f349f448a3af05cc
Author: niko <329872193@qq.com>
Date: Wed Nov 2 10:27:47 2016 +0800

hello

开始cherry-pick


这次, 我们按照正确的顺序来:

$ git cherry-pick 42a8708 ceaa73f
[niko_blog_test-2 fdae77f] Add: txt-01.
1 file changed, 2 insertions(+), 1 deletion(-)
[niko_blog_test-2 3e02126] Add: txt-02.
1 file changed, 2 insertions(+), 1 deletion(-)

因为不会冲突, 直接用分支niko_blog_test的commit log, 如 git log 所示:

$ git log
commit 3e02126c34fd3909b34228368ffb98c400b436c9
Author: niko <329872193@qq.com>
Date: Wed Nov 2 14:54:39 2016 +0800

Add: txt-02.

commit fdae77ffb6583fc44a82ab36cb26f005f335bacb
Author: niko <329872193@qq.com>
Date: Wed Nov 2 14:54:11 2016 +0800

Add: txt-01.

commit f000b1ac4bf9dbd57d107895f349f448a3af05cc
Author: niko <329872193@qq.com>
Date: Wed Nov 2 10:27:47 2016 +0800

hello

顺序对了, 是不是简单很多啦? 所以一定要注意顺序的问题. 嘻嘻……

参考


git-cherry-pick