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 校验和。
下面是这个命令的图解示例。
图解示例
如下有两个分支master
和dev
,从C2
开始两个分支开始有不同的commits。
需要把dev
的C6
合并到master
,只需在master
分支上执行git cherry-pick C6
,就会把dev
分支的C6
应用到master
分支上并产生一个新的commitC6'
。
如果要合并多个commits,比如C7
和C8
两个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 校验和从commit1
到commitn
的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的提交保持不变。