Git 中的挑选提交

Avatar of Tobias Günther
Tobias Günther

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

本文是我们 “高级 Git” 系列的一部分。请务必关注我们的 Twitter订阅我们的新闻通讯,以了解后续文章!

在本系列的第 5 部分中,我们了解了变基和合并。尽管git mergegit rebase之间存在一些差异,但这两个命令的目标相同:它们将更改从一个分支集成到另一个分支。

今天,我们将了解git cherry-pick以及它如何允许我们将任何分支中的选定、单个提交集成到我们当前的HEAD分支中。这与git mergegit rebase有很大区别,这两者都将指定分支中的所有新提交集成在一起。

那么为什么要这样做,只选择一个分支中的一个提交并将其应用到另一个分支呢?当然,原因有很多,但特别有用的是撤消更改。假设您不小心在错误的分支上进行了提交。使用cherry-pick这不是什么大问题:您可以切换到正确的分支,然后挑选提交!

高级 Git 系列


在我们查看实际示例之前,需要提醒您一句:不要对挑选提交过于兴奋。您的主要目标应该是基于分支级别进行工作,并且git mergegit rebase都是为此目的而构建的。挑选提交仅适用于特殊场合,不能替代合并和变基。

将提交移动到另一个分支

Showing a flow of two git branches, one for master and another for feature/newsletter. A red circle representing a third commit is on the master branch, but has a yellow arrow pointing to the feature/newsletter branch showing where it was intended to go.

以下是一个现实场景,用于解释何时挑选提交是正确的方法。假设您将某些内容提交到了master分支,但实际上应该提交到feature/newsletter。现在怎么办?您是否需要联系团队成员或您的老板来解释这个“错误”?

以下Tower(适用于 macOS 和 Windows 的图形化 Git 客户端)的屏幕截图显示了问题以及意外在master分支上进行的提交26bf1b48

Showing the Tower app UI with a commit history of a master branch. Red arrows point to the most recent commit and the newsletter branch,. indicating that is where the commit was intended to go.

或者,如果您在终端中键入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 应用程序,则整个过程如下所示。

Animated screenshot showing a commit being dragged from master branch and dropped on the feature/newsletter branch where it was intended to go.

一种适用于特殊情况的工具,而不是日常集成

只要您可以使用传统的合并或变基,就应该这样做。挑选提交应该保留在无法使用git mergegit rebase的情况下,或者当您只想将单个提交从一个分支移动到另一个分支时。始终记住git cherry-pick会创建“重复”提交,并且您应该在之后进行清理。

如果您想更深入地了解高级 Git 工具,请随时查看我的(免费!)“高级 Git 工具包”:它是一系列关于分支策略、交互式变基、Reflog、子模块等主题的简短视频的集合。

祝您挑选提交愉快——并在我们关于“高级 Git”系列的下一部分中与您相见!

高级 Git 系列