Git:Cherry-Pick 桃色陷阱

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/J2b130UVF0aPoHM9-U9Uuw

Cherry-Pick 咋一看这名字就很时髦,用来干啥呢?

Cherry-Pick 是什么?

假设在开发某些功能或者修复 bug 的时候把代码 commit 到了错误的分支 A,并且分支 A 最新版本已经覆盖了该 commit。看到这样你不会抓狂?被逼无奈之下,你可能会这样补救一番:

首先,切换到分支 A,找到需要备份的 commit 内容,逐个备份出来,并且保存 commit 描述,然后再切换回将要接收合并的目标工作分支,接着把备份的内容逐个更新到当前分支中,最后再提交新的 commit 并且填上前面保存下来的 commit 描述。

如果更新内容庞大,没有相关指令可以自动化实现上面的操作,全程靠手动操作,那么估计 Ctrl + C/V 都会罢工。

幸运的是,Git 其实提供了这样一个命令 cherry-pick 帮助我们一步实现上面的补救措施。其命令格式是

git cherry-pick <commit-hash>

上面的命令格式中,commit-hash 是在提交 commit 时 git 自动生成的 hash 串,代表每个独一无二的 commit。

Cherry-Pick 用于从其它分支提取某些 commit,并且合并到当前工作分支,同时还会把之前提交的描述也拷贝进来。这样大大简化了拉取其他分支某个 commit 的难度。

为何要用 Cherry-Pick

在多人合作的团队项目中,管理员通常会创建一个主线分支,比如命名为 develop,然后允许各个开发者基于主线分支分叉出特性分支,并在各自特性分支上进行特性功能的开发。在特性分支上,功能开发验证完毕后,开发人员再提交 merge 合并请求,将特性分支合并到主线分支,合并请求由管理员审核通过后才执行具体合并动作。

这里边,在合并分支内容时,有些情况需要分开讨论。

如果,特性分支最终开发完毕,并得到完整的认可,那么可以采用 merge 操作将特性分支新增的所有 commits 都合并到主线分支。

可是,如果在特性分支没有开发完毕又被遗忘很久远的时候,后来想想又需要用到其中的部分更新内容,比如,bug 补丁等,那么这个特性分支里的部分 commit 才是值得被拉取的内容,用 merge 明显不行,应该用 cherry-pick。

既然 cherry-pick 和 merge 都是用于合并 commit,那么区别在哪?

Cherry-Pick 只针对某个分支的某些指定 commit,而不是全部,而 merge 会把被选中分支的所有不同 commit 都拉取过来,这正是 cherry-pick 和 merge 的核心区别所在。

此外,类似合并功能的命令还有 rebase,后边有机会再撩她。

怎么使用 Cherry-Pick

多人开发的团队项目在代码管理上,很多麻烦的操作(例如合并分支代码等)都在类似 Gitlab 的平台上进行,平台能够尽最大限度规范化推行代码的合并。关于 Gitlab 的介绍,可以查看八戒以前写的文章《在局域网搭建一个带 web 操作页面的 git 版本服务器 - Gitlab》。

当然,如果接收合并内容的分支不受管控,完全可以自己在本地通过 git 命令合并或者用集成 git 功能的客户端可视化操作。带有 git 功能的可视化客户端也比较多,例如 TortoiseGit、SourceTree 和各大热门 IDE 等。

接下来选择使用 git 命令来简单做个示例。

准备一个本地代码仓库

$ cd ~
$ mkdir sample && cd sample
$ git init
Initialized empty Git repository in ~/sample/.git/

添加第一个改动,这里创建一个文本文件 index.txt 并写入字符串 index,然后提交到默认分支 master

$ echo index>index.txt
$ git add .
$ git commit -m "add index file"
[master (root-commit) e423b8c] add index file1 file changed, 1 insertion(+)create mode 100644 index.txt
$ git status
On branch master
nothing to commit, working tree clean

再准备两个特性分支 A 和 B

$ git branch A
$ git branch B
$ git branchAB
* master

git branch 命令只会创建新分支,但不会切换。

切换到特性分支 B 开始特性开发,这里为演示起见单纯创建一个文件 feature.txt 并写入字符串 feature,然后将工程更新提交到当前分支 B

$ git switch B
Switched to branch 'B'
$ echo feature>feature.txt
$ ll
total 2
-rw-r--r-- 1 Administrator 197121 8 Nov  8 19:22 feature.txt
-rw-r--r-- 1 Administrator 197121 6 Nov  8 19:10 index.txt
$ git add .
$ git commit -m "create feature"
[B a827145] create feature1 file changed, 1 insertion(+)create mode 100644 feature.txt
$ git log --oneline
a827145 (HEAD -> B) create feature
e423b8c (master, A) add index file

可以看到本地工作目录,在只有 index.txt 文件的基础上,多了个 feature.txt 文件。

除了 git switch 可以切换分支,还有 git checkout 也可,两者作用基本一样,但是建议统一使用 switch,避免记忆负担。

使用 git log 查看当前分支的提交日志,后边的选项 --oneline 会将日志信息简化到一行,方便查看提交记录比较多的情况。

当特性开发到这个阶段时,突然发现工程代码其实有个 bug,自己发现—高兴坏了。既然分支 B 和 分支 A 都是从主线分支分叉而来,那么分支 A 的代码中也会存在同样的 bug。

着手修复分支 B 的 bug,这里简单起见只是创建一个文件 fix.txt 并写入字符串 fix,然后提交更新到仓库

$ echo fix>fix.txt
$ git add .
$ git commit -m "fix bug"
[B 797dfa4] fix bug1 file changed, 1 insertion(+)create mode 100644 fix.txt
$ git log --oneline
797dfa4 (HEAD -> B) fix bug
a827145 create feature
e423b8c (master, A) add index file

那么怎么把分支 B 里刚刚修复的 bug 更新应用到分支 A 中呢?如果使用 merge 合并,那么分支 B 中还未开发完成的特性功能也会被一起同步到分支 A 中,这样不是我们想要的结果,于是可以针对某些已提交的 commit 执行 git cherry-pick。

在执行 cherry-pick 时需要已提交 commit 的 hash。从上面分支 B 的提交日志可以找到这串 hash

...
797dfa4 (HEAD -> B) fix bug
...

797dfa4 就是我们需要的 commit hash,虽然它不是一串完整的 hash,但是 git 只对比前面一部分就够了。

切换到分支 A 中,然后 cherry-pick

$ git switch A
Switched to branch 'A'
$ git log --oneline
e423b8c (HEAD -> A, master) add index file
$ git cherry-pick 797dfa4
[A e27c778] fix bugDate: Wed Nov 8 19:48:36 2023 +08001 file changed, 1 insertion(+)create mode 100644 fix.txt$ ll
total 2
-rw-r--r-- 1 Administrator 197121 4 Nov  8 20:01 fix.txt
-rw-r--r-- 1 Administrator 197121 6 Nov  8 19:10 index.txt
$ git log --oneline
e27c778 (HEAD -> A) fix bug
e423b8c (master) add index file

可以看到执行 git cherry-pick 后,本地目录下也有了 fix.txt 文件,也即是分支 B 中做了修复 bug 的更新内容已经同步到分支 A 中,合并结果成功。

陷阱

上面的合并过程是很理想化的顺利,但是现实往往有些棘手。

比如,在分支 B 中,如果当时开发特性功能时刚好修改了有几行主线分支的原有代码,而修复 bug 时同样改动了这几行代码,那么在 cherry-pick 时有极大可能会出现合并冲突,导致合并失败,这时需要手动再处理冲突的代码段,保留符合修复 bug 意图的代码。

这种冲突,在 merge 操作中也很常见,原因基本类似。

所以说,cherry-pick 虽然很强大,但不是万能的,不要过度使用,使用时应该谨慎。

一般在 merge 合并操作能满足使用需求的情况下,优先建议使用 Merge,而不是 cherry-pick,只有在两个分支不是可以完全合并的前提下,再考虑使用 cherry-pick。因为 cherry-pick 在设计时就是为了解决某些指定 commit 的合并,而非全部。

这就是 cherry-pick 的桃色陷阱,你说呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/276803.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

maven打包插件maven-jar-plugin与spring-boot-maven-plugin

maven几种打包插件介绍 文章目录 &#x1f50a;1.spring-boot-maven-plugin打包后效果 &#x1f4d5;2.maven-jar-plugin打包后效果&#x1f58a;️最后总结 &#x1f50a;1.spring-boot-maven-plugin <plugins><plugin><groupId>org.springframework.boot&…

Unity中 URP Shader 常量缓冲区CBUFFER

文章目录 前言一、常量缓冲区CBUFFER 使用步骤1、在属性面版定义我们需要使用的属性2、在Pass中&#xff0c;使用前需要提前声明3、使用时&#xff0c;直接使用即可 二、使用 常量缓冲区CBUFFER 的好处三、ShaderGraph属性 和 对应Shader的功能1、我们创建一个颜色属性2、使用&…

用“价值”的视角来看安全:《构建新型网络形态下的网络空间安全体系》

作者简介&#xff1a; 懒大王敲代码&#xff0c;正在学习嵌入式方向有关课程stm32&#xff0c;网络编程&#xff0c;数据结构C/C等 今天给大家介绍《构建新型网络形态下的网络空间安全体系》这本书&#xff0c;希望大家能觉得实用&#xff01; 欢迎大家点赞 &#x1f44d; 收藏…

Java基础知识复习

目录 一、Java语言基础知识&#xff0c;包括面向对象编程、语法特性等 0、什么是面向对象编程&#xff1f; 1、基本语法&#xff1a; 2、变量和数据类型&#xff1a; 3、运算符和表达式&#xff1a; 4、控制结构&#xff1a; 5、函数和方法&#xff1a; 6、类和对象&#xff1a…

后端打印不了trace等级的日志?-SpringBoot日志打印-Slf4j

在调用log变量的方法来输出日志时&#xff0c;有以上5个级别对应的方法&#xff0c;从不太重要&#xff0c;到非常重要 调用不同的方法&#xff0c;就会输出不同级别的日志。 trace&#xff1a;跟踪信息debug&#xff1a;调试信息info&#xff1a;一般信息warn&#xff1a;警告…

JVM调优:参数(学习笔记)

一、jvm的运行参数 标准参数 -help、-version、-D参数 jvm的标准参数&#xff0c;一般都是很稳定的&#xff0c;在未来的JVM版本中不会改变&#xff0c;可以使用java -help 检索出所有的标准参数。 通过以下命令查看&#xff1a; 命令&#xff1a;java -help 可以看到我们经常…

批发订货程序推荐 订货系统哪个好

订货系统是一种企业管理软件&#xff0c;可以让批发商、门店实时掌握客户订单的进度和完成情况&#xff0c;提高企业与客户之间的沟通效率&#xff0c;减少错误&#xff0c;节省时间和成本。因此&#xff0c;目前很多企业会选择订货系统来帮助提高业务效率&#xff0c;但目前市…

51单片机应用从零开始(十一)·数组函数、指针函数

51单片机应用从零开始&#xff08;九&#xff09;数组-CSDN博客 51单片机应用从零开始&#xff08;十&#xff09;指针-CSDN博客 目录 1. 用数组作函数参数控制流水花样 2. 用指针作函数参数控制 P0 口 8 位 LED 流水点亮 1. 用数组作函数参数控制流水花样 要在51单片机中…

SpringBoot Maven 项目打包的艺术--主清单属性缺失与NoClassDefFoundError的优雅解决方案

Maven项目的Jar包打包问题-没有主清单属性&&ClassNotFoundException 与 NoClassDefFoundError 文章目录 Maven项目的Jar包打包问题-没有主清单属性&&ClassNotFoundException 与 NoClassDefFoundError1、问题出现1.1、Jar包运行&#xff1a;没有主清单属性解决方…

【运维】Kafka高可用: KRaft(不依赖zookeeper)集群搭建

文章目录 一. kafka kraft 集群介绍1. KRaft架构2. Controller 服务器3. Process Roles4. Quorum Voters5. kraft的工作原理 ing 二. 集群安装1. 安装1.1. 配置1.2. 格式化 2. 启动测试2.1. 启功节点服务2.2. 测试 本文主要介绍了 kafka raft集群架构&#xff1a; 与旧架构的不…

typedef的使用

在C语言中&#xff0c;有一个关键字叫做typedef&#xff0c;有些人对此感到很疑惑。不熟悉此知识的同学都会对编程失去细心&#xff0c;直接劝退&#xff08;因为之前我就是这样&#xff09;。、 因为好不容易认识了C语言中所有的关键字&#xff08;就是类型吧&#xff0c;像啥…

python爬虫学习-批量爬取图片

python爬虫学习-批量爬取图片 爬虫步骤爬取前十页图片到本地根据页码获取网络源码使用xpath解析网页解析网页并下载图片主函数如下 爬取的网站为站长素材&#xff08;仅做学习使用&#xff09; 爬取的目标网站为 https://sc.chinaz.com/tupian/qinglvtupian.html如果爬取多页&…