本文是我们 “高级 Git” 系列的一部分。请务必关注我们的 Twitter 或订阅我们的新闻通讯,以了解后续文章!
在本系列的第 5 部分中,我们了解了变基和合并。尽管git merge
和git rebase
之间存在一些差异,但这两个命令的目标相同:它们将更改从一个分支集成到另一个分支。
今天,我们将了解git cherry-pick
以及它如何允许我们将任何分支中的选定、单个提交集成到我们当前的HEAD
分支中。这与git merge
或git rebase
有很大区别,这两者都将指定分支中的所有新提交集成在一起。
那么为什么要这样做,只选择一个分支中的一个提交并将其应用到另一个分支呢?当然,原因有很多,但特别有用的是撤消更改。假设您不小心在错误的分支上进行了提交。使用cherry-pick
这不是什么大问题:您可以切换到正确的分支,然后挑选提交!
高级 Git 系列
- 第 1 部分:在 Git 中创建完美的提交
- 第 2 部分:Git 中的分支策略
- 第 3 部分:使用拉取请求进行更好的协作
- 第 4 部分:合并冲突
- 第 5 部分:变基与合并
- 第 6 部分:交互式变基
- 第 7 部分:Git 中的挑选提交(您现在所处的位置!)
- 第 8 部分:使用 Reflog 恢复丢失的提交
在我们查看实际示例之前,需要提醒您一句:不要对挑选提交过于兴奋。您的主要目标应该是基于分支级别进行工作,并且git merge
和git rebase
都是为此目的而构建的。挑选提交仅适用于特殊场合,不能替代合并和变基。
将提交移动到另一个分支

以下是一个现实场景,用于解释何时挑选提交是正确的方法。假设您将某些内容提交到了master
分支,但实际上应该提交到feature/newsletter
。现在怎么办?您是否需要联系团队成员或您的老板来解释这个“错误”?
以下Tower(适用于 macOS 和 Windows 的图形化 Git 客户端)的屏幕截图显示了问题以及意外在master
分支上进行的提交26bf1b48

或者,如果您在终端中键入git log
,则可以检查命令行上的情况。
$ git log
commit 26bf1b4808ba9783e4fabb19ec81e7a4c8160194 (HEAD -> master)
Author: Tobias Günther
Date: Fri Oct 5 09:58:03 2018 +0200
Newsletter signup page
因此,ID 为26bf1b48
的提交最终进入了master
,但您应该将其提交到feature/newsletter
分支。让我们挑选该特定提交并将其移动到正确的分支。首先,您切换分支,然后挑选提交。
$ git checkout feature/newsletter
Switched to branch 'feature/newsletter'
$ git status
On branch feature/newsletter
nothing to commit, working tree clean
$ git cherry-pick 26bf1b48
[feature/newsletter 7fb55d0] Newsletter signup page
Author: Tobias Günther <[email protected]>
Date: Fri Oct 5 09:58:03 2018 +0200
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 signup.html
如果您再次运行git log
,您可以在feature/newsletter
分支上看到新的提交。
$ git log
commit 7fb55d06a8e70fdce46921a8a3d3a9de7f7fb8d7 (HEAD -> feature/newsletter)
Author: Tobias Günther <[email protected]>
Date: Fri Oct 5 09:58:03 2018 +0200
Newsletter signup page
后台发生了什么?Git 在feature/newsletter
分支上创建了具有相同更改和相同提交消息的提交副本。但是,它是一个具有其自身新 ID 的全新提交。那么原始提交呢?
清理另一个分支
如果您检查master
分支,您仍然可以看到该“错误”提交。这意味着挑选提交不会将挑选的提交“移动”出原始分支;它只是创建了一个副本,并保持原始提交不变。
现在,为了清理并撤消提交,您可以使用git reset
。
$ git checkout master
Switched to branch 'master'
$ git reset --hard HEAD~1
HEAD is now at 776f8ca Change about title and delete error page
就是这样——就像什么也没发生一样。
如果您使用的是像 Tower 这样的 GUI 应用程序,则整个过程如下所示。

一种适用于特殊情况的工具,而不是日常集成
只要您可以使用传统的合并或变基,就应该这样做。挑选提交应该保留在无法使用git merge
或git rebase
的情况下,或者当您只想将单个提交从一个分支移动到另一个分支时。始终记住git cherry-pick
会创建“重复”提交,并且您应该在之后进行清理。
如果您想更深入地了解高级 Git 工具,请随时查看我的(免费!)“高级 Git 工具包”:它是一系列关于分支策略、交互式变基、Reflog、子模块等主题的简短视频的集合。
祝您挑选提交愉快——并在我们关于“高级 Git”系列的下一部分中与您相见!
高级 Git 系列
- 第 1 部分:在 Git 中创建完美的提交
- 第 2 部分:Git 中的分支策略
- 第 3 部分:使用拉取请求进行更好的协作
- 第 4 部分:合并冲突
- 第 5 部分:变基与合并
- 第 6 部分:交互式变基
- 第 7 部分:Git 中的挑选提交(您现在所处的位置!)
- 第 8 部分:使用 Reflog 恢复丢失的提交