计算机基础

Git Cherry Pick详解

1. 简介


Git是一款分布式版本控制系统,它提供了许多强大的功能来管理代码的版本和变更。其中之一就是cherry-pick命令,它允许我们选择某个分支上的一个或多个提交,并将它们应用到当前分支上。这个功能非常有用,可以帮助我们在不合并整个分支的情况下,将特定的提交应用到其他分支上。本篇博客将详细介绍cherry-pick命令的使用方法和示例。

2. cherry-pick命令的基本用法



cherry-pick命令的基本语法如下:

git cherry-pick <commit>

其中,<commit>是要应用的提交的哈希值或分支名。该命令会将指定的提交应用到当前分支上,并创建一个新的提交。

3. cherry-pick的使用场景


cherry-pick命令常用于以下场景:

  • 合并单个提交:当我们只想应用某个分支上的一个提交到当前分支时,可以使用cherry-pick命令,而不需要合并整个分支。
  • 修复bug:当我们在一个分支上修复了一个bug,并希望将这个修复应用到其他分支上时,可以使用cherry-pick命令。
  • 提取特定功能:当我们在一个分支上开发了一个新功能,并希望将该功能应用到其他分支上时,可以使用cherry-pick命令。

4. cherry-pick的示例


在多分支开发的时候会有需要把一个分支的部分commit应用到其他的分支上,然而git merge会把一个分支的commits都应用到当前分支,这时候我们可以使用git cherry-pick来完成这一操作,它的作用是选择已存在的commit应用到当前分支上,并产生新的commit SHA-1 校验和。

下面是这个命令的图解示例。

图解示例

如下有两个分支masterdev,从C2开始两个分支开始有不同的commits。

需要把devC6合并到master,只需在master分支上执行git cherry-pick C6,就会把dev分支的C6应用到master分支上并产生一个新的commitC6'

如果要合并多个commits,比如C7C8两个commits,可以执行git cherry-pick C7 C8,则git提交记录就会变成下面这样。

需要注意的是,新的commit SHA-1 校验和会和原来的commit SHA-1 校验和不一样。

下面我们来动手感受一下。先准备一下git的提交记录,示例如下图:

这个时候master分支有C1,C2,C3,C4文件,dev分支有C1,C2,C5,C6,C7,C8,C9文件。

接下来我们把dev分支的一些commits应用到master分支:

  • 根据之前的终端记录或者通过git log dev查看C6的 SHA-1 校验和是fca3793,在master分支上执行git cherry-pick fca3793,可以看到新增了一个 SHA-1 校验和为50982a2的commit并且在master分支上多了一个C6文件。
  • 执行git cherry-pick d67e9f6 7bf5e7d之后,master分支又多了C7,C8两个文件。

其他用法

  • 如果想应用连续的多个commits还可以使用git cherry-pick commit1..commitn,应用 SHA-1 校验和从commit1commitn的commits,注意这里并不包含commit1,如果需要包含可以执行git cherry-pick commit1^..commitn
  • 如果只想把某一个分支最后一个commit应用到当前分支,可以直接使用git cherry-pick branch-name,这个命令的效果是,将branch-name分支最后一个commit应用到当前分支。
  • 当然实际使用过程中,使用cherry-pick可能会出现冲突,例如提示如下:

解决冲突再执行git add <paths>将文件标记为以解决冲突,或者执行git rm <paths>直接从暂存区和工作区删除文件,最后执行git cherry-pick --continue,则完成这次cherry-pick

如果想要取消这次的cherry-pick操作可以执行git cherry-pick --abort

附:Cherry Pick 和 merge, rebase的区别


GIT分支机构概述

在GIT中,每个提交都知道其父级。因此,您的GIT提交列表是一个单向链接列表,代表了提交的顺序。默认情况下,您正在使用一个名为master的分支。分支始终存储为简单的哈希ID,这是分支上最新提交的哈希ID。您可以随时通过git branch branch_name命令基于当前HEAD提交启动新分支。该命令创建一个新分支,指向当前提交。然后您可以通过git checkout branch_name更改到该分支。这会将您的HEAD更改为您的分支。或者,您可以通过键入git checkout -b branch_name一起执行这些步骤。

在分支上,您可以独立于主分支工作。您可以实现新功能,修复错误或进行一些重构。同时,其他人在master分支或其他一些分支上工作。在开始使用功能之前,新功能将添加到master分支中。此时,您必须创建一个版本,其中包含当前主版本的所有内容以及分支中的更改。有三种方法可以做到这一点。让我们看看细节。

Merge

第一种非常经典的方法是git merge。在master分支上(您始终可以通过输入git branch来检查当前分支),键入git merge your_branch。此命令将创建对master分支的新合并提交。

什么是合并提交?

在GIT中,每个提交只有一个父提交,但合并提交有两个甚至更多个父提交。git merge master命令创建一个具有两个父级的合并提交:分支的最后一次提交和master的最后一次提交。这样,通过签出此提交,您将在主数据库和分支机构上都拥有更改。在合并期间,如果在两个分支上修改了相同的行,则可能会出现冲突。在这种情况下,必须手动解决这些冲突。

合并之前,请始终确保您的分支与远程分支是最新的。

git merge最大的优点是提交的历史记录保持清晰和不变。

缺点是大量的合并提交会使分支历史记录不可读。

Rebase

第二个选项是git rebase。Git rebase正在更改分支上第一次提交的父级。因此,git rebase master会将分支的第一次提交的父级更改为master分支上的最新提交。

为此,需要修改分支上的所有提交,因为这样,它们将包含在主服务器上所做的更改。由于您正在更改提交,因此其哈希ID也将更改。因此,从技术上讲,它们将是新的提交。这也意味着同一提交的多个实例(基于和不基于)可以在git日志中出现。您真的要注意!

此外,git rebase是通过commit提交来完成的,因此相同的冲突会一次又一次地出现。

此方法的优点是您的历史记录将保持一条直线,另一方面,以后将无法确定git rebase发生了。

如果多个开发人员在同一个分支上工作,则应特别注意重新编制基准(rebasing)。

总结


  • 总结一下主题:git merge不会更改任何现有的提交,它只是创建一个新的合并提交,该提交具有两个或多个父级。
  • Git rebase更改了一个提交的父级(通常是分支的根,或作为参数给出的提交)。换句话说,它正在重写分支(或提交)的历史记录。提交将获得新的哈希ID。
  • Git cherry-pick使用新的提交ID在当前分支上重新应用一个专用主​​题。cherry-picked的提交保持不变。