Git进阶系列 | 5. Rebase vs Merge

news2024/11/18 1:32:45

Git是最流行的代码版本控制系统,这一系列文章介绍了一些Git的高阶使用方式,从而帮助我们可以更好的利用Git的能力。本系列一共8篇文章,这是第5篇。原文:Rebase vs. Merge: Integrating Changes in Git[1]

大多数开发人员都理解在Git中使用分支的重要性,事实上,本系列已经有一篇关于Git分支策略的文章,解释了Git强大的分支模型、不同类型的分支以及两种最常见的分支工作流。总而言之,在独立的容器中工作(即分支),是非常有用的,也是使用版本控制系统的主要原因之一。

本文我们将研究如何集成分支,如何将新代码添加回现有的开发线路中?有不同的方法可以实现这一点。在这篇“Git进阶”系列的第五部分我们要讨论Git中的集成更改,即合并和rebase。

在我们深入细节之前,重要的是要理解这两个命令,git mergegit rebase。它们解决了相同的问题,即将一个Git分支的更改集成到另一个分支,只是做法稍有不同。下面我们从git merge开始。

Git进阶系列:

  1. 创建完美的提交
  2. Git中的分支策略
  3. 基于Pull Request实现更好的协作
  4. 合并冲突
  5. Rebase vs Merge(本文)
  6. 交互式Rebase
  7. Git中的Cherry-pick提交
  8. 用Reflog恢复丢失的提交

理解合并

要将一个分支合并到另一个分支,可以使用git merge命令。假设在ranch-B上有一些新提交,现在我们想把这个分支合并到另一个分支branch-A中。为此,可以这样输入:

$ git checkout branch-A
$ git merge branch-B

如此,Git会在当前工作分支(本例中为branch-A)中创建一个新的合并提交,连接两个分支的历史记录。为了完成这个任务,Git需要查找三个提交:

  • 第一个是“公共祖先提交(common ancestor commit)”。如果跟踪一个项目中两个分支的历史,总是至少有一个公共提交。此时,两个分支具有相同的内容。在那之后,就向不同方向进化。
  • 另外两个有趣的提交是每个分支的端点,即它们的当前状态。请记住,集成的目的是组合两个分支的当前状态。因此,他们的最新修订当然很重要。

结合这三个提交可以执行我们想要的集成。

alt

无可否认,这是一个简化场景,两个分支中的一个(branch-A)自创建以来没有任何新的提交,这在大多数软件项目中是不太可能的。因此,它在本例中的最后一次提交也是公共祖先(common ancestor)

在这种情况下,集成非常简单,Git可以将所有来自branch-B的新提交添加到公共祖先提交之上。在Git中,这种最简单的集成形式称为“快进(fast-forward)”合并,然后两个分支共享完全相同的历史(并且不需要额外的“合并提交”)。

alt

然而大多数情况下,两个分支将以不同的提交向前推进。我们举一个更现实的例子:

alt

为了集成,Git必须创建一个包含所有更改的新提交,并注意分支之间的差异,这就是我们所说的合并提交(merge commit)

人工提交和合并提交

通常情况下,提交是由人精心创建的,是一个有意义的单元,只包含相关的变更,以及包括了上下文和注释的有意义的提交信息。

现在,合并提交有点不一样,它不是由开发人员创建的,而是由Git自动创建的。而且,合并提交不一定包含“相关更改的语义集合”。相反,它的目的只是连接两个(或更多)分支。

alt

如果想了解这样的自动合并操作,必须查看所有分支的历史以及各自的提交历史。

Rebase集成

在讨论rebase之前,先说清楚一点: rebase并不比合并更好或更差,只是不同而已。也许你只需要通过合并集成分支,就可以完成工作,甚至不需要考虑rebase。不过,理解rebase是做什么的,并了解它的优缺点,确实很有帮助。也许你会在某个项目中遇到某个问题,而rebase恰好很有帮助…

好吧,我们开始!还记得刚刚讲的自动合并提交吗?有些人不太喜欢这些,宁愿不用。另外一些开发人员喜欢项目历史看起来像一条直线,没有任何迹象表明它在某个点上被分成了多个分支,即使这些分支已经被集成了。这基本上就是Git rebase过程中发生的事情。

alt

一步一步rebase

让我们逐步介绍rebase操作。和前面的例子一样,一开始是这样的:

alt

我们想要将branch-B的更改集成到branch-A中,但这次是用rebase,而不是合并。实际的Git命令非常简单:

$ git checkout branch-A
$ git rebase branch-B

类似于git merge命令,只需要告诉git想要集成哪个分支。我们来看看幕后故事……

alt

第一步,Git将“删除”发生在公共祖先提交之后的所有对branch-A分支的提交。别担心,它们不会被丢弃,可以将这些提交视为被暂时保存在一个安全的地方。

alt

第二步,Git应用来自branch-B的新提交。此时,两个分支暂时看起来完全相同。

alt

最后,集成那些“暂存”的提交(来自branch-A的新提交)。由于它们位于branch-B分支的顶部,所以是rebase的。

因此,项目历史看起来就像是在一条直线上进行开发,不存在包含所有合并更改的合并提交,并且保留了原始提交结构。

rebase的潜在隐患

还有一件事对于理解Git rebase很重要,它重写了提交历史。再看一下最后一张图表,提交C3*带有星号,虽然C3*C3具有相同的内容,但实际上是不同的提交。为什么?因为它在rebase之后有一个新的父提交。在rebase之前,C1是父提交。在rebase之后,父提交是C4,它被rebase到了C4

一个提交只有少量重要属性,比如作者、日期、变更集和父提交,更改任何这些信息都会创建一个全新的提交,有一个新的SHA-1哈希ID。

对于尚未发布的提交,这样重写历史记录不是问题。但是,如果正在重写的是已经推送到远端代码库的提交,可能会遇到麻烦。也许其他人的工作是基于最初的C3提交的,现在它突然不存在了……

为了远离麻烦,这里有一个使用rebase的简单规则: 永远不要在公共分支上使用rebase,比方说已经被推送到远端代码库的提交!相反,只在将它集成到共享的团队分支之前,才使用git rebase来清理本地提交历史。

集成就是一切!

归根到底,merge和rebase都是有用的Git策略,用哪个取决于想要实现的目标。合并是非破坏性的,因为合并不会改变现有的历史。另一方面,rebase可以通过避免不必要的合并提交来帮助清理项目历史记录。只要记住不要在公共分支中这样做,从而避免干扰其他开发人员。

如果想更深入了解高级Git工具,可以免费查看“Advanced Git Kit[3]”: 这是关于分支策略、交互式Rebase、Reflog、子模块等主题的短视频集合。

References:
[1] Rebase vs. Merge: Integrating Changes in Git: https://css-tricks.com/rebase-vs-merge-integrating-changes-in-git/

你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind

- END -

本文由 mdnice 多平台发布

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【五子棋实战】第4章 部署五子棋计算接口到Window、Linux上

【五子棋实战】第4章 部署五子棋计算接口到Window、Linux上 python项目打包成exe可执行文件 ## 步骤一、安装pyinsatller ## 步骤二、使用pyinstaller打包Python程序 ## 操作演示 ## 注意事项!! python的Flask接口部署(Linux) ##…

二叉树-理论基础

文章目录 前言一、二叉搜索树平衡二叉搜索树 二、二叉树的存储方式二叉树的遍历方式二叉树的定义总结 前言 二叉树有两种主要的形式:满二叉树和完全二叉树。满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上…

16.vant Weapp

目录 1 使用npm 2 安装 vant 3 构建npm 4 去除 style:v2 5 使用 vant 6 样式变量 1 使用npm 微信小程序不支持下面三种包 不支持依赖 Node.js 内置库的包不支持依赖 浏览器内置对象 的包不支持依赖 C插件 的包 除去上面三种,能用的包就不多了&#…

面向AI的新编程范式

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 联合制作 / 声网 产品统筹 / bobo 录音间 / 声湃轩北京站 在这期播客节目中,我们将探讨AI与程序员如何共同进步。随着AI热潮席卷全球,许多程序员尝试着使…

python爬虫_python基础数据类型

文章目录 ⭐前言⭐python💖 Number💖 String💖 List💖 Tuple💖 Dict ⭐结束 ⭐前言 大家好,我是yma16,本文分享关于python的基础数据类型,作为python爬虫专栏的基石。 ⭐python 发…

【Note8】网络管理

文章目录 1.MII介绍2.BMC MAC3.MDIO&MDC4. 1.MII介绍 SOC内部没有网络MAC外设:缺:网络效率不高,一般芯片内置的MAC会网络加速引擎,如网络专用DMA,网络处理效率会很高。 SOC内部集成网络MAC外设:MII/RM…

【MySQL】不就是子查询

前言 今天我们来学习多表查询的下一个模块——子查询,子查询包括了标量子查询、列子查询、行子查询、表子查询,话不多说我们开始学习。 目录 前言 目录 一、子查询 1. 子查询的概念 2. 子查询语法格式 2.1 根据子查询结果不同可以分为:…

C++——内联函数

目录 1. 概念 2.特性 3. 经典面试题 1. 概念 以inline修饰的函数叫做内联函数,编译时C编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。 以Add函数为例: int Add(int x, int y) {int z x…

RabbitMQ基础与实操复习

RabbitMQ基础复习 1、MQ引言1.1 什么是MQ1.2 MQ有哪些1.3 不同MQ特点 2、RabbitMQ引言2.1 RabbitMQ2.2 RabbitMQ安装 3、RabbitMQ配置3.1 RabbitMQ命令行3.2 Web管理界面3.2.1 overview概览3.2.2 Admin用户和虚拟主机管理 4、RabbitMQ常用消息模型测试4.1 RabbitMQ支持的消息模…

RabbitMQ应用场景和集群搭建复习

RabbitMQ应用场景和集群搭建 1. MQ的应用场景1.1 异步处理1.2 应用解耦1.3 流量削峰 2、RabbitMQ集群搭建2.1 普通集群(副本集群)2.1.1 架构图2.1.2 集群搭建1、集群规划:这里用三台虚拟机测试2、克隆三台机器主机名和ip映射3、 在其他两台节点上安装rabbitmq4、后台…

Neurophotonics | HyperOptoNet:用于fNIRS超扫描脑间神经同步分析的MATLAB工具箱

导读 意义:本研究开发了一个基于MATLAB的工具箱,用于脑间同步(IBS)分析,并进行了实验研究以验证其性能。据所知,这是第一个基于功能近红外光谱(fNIRS)超扫描数据的IBS工具箱,可在两个三维(3D)头部模型上直观地显示结果…

Elasticsearch:analyzer

前奏 es的chinese、english、standard等分词器对中文分词十分不友好,几乎都是逐字分词,对英文分词比较友好。 在kibana的dev tools中测试分词: POST /_analyze {"analyzer": "standard","text": "你太…

用OpenCV进行透视变换

1. 引言 欢迎回来!今天我们将焦点聚焦在我在图像处理中最喜欢的话题之一——透视变换。使用该技术,可以灵活方便的实现各种各样好玩的特效。 闲话少说,我们直接开始吧! 2. 单应矩阵 我们首先展开对单应矩阵的深入研究。作为图…

车载-惯性导航系统

概念 惯性导航系统是一种不受电磁波干扰,且不依靠外界信号即可完成自主定位的导航系统。 惯性导航系统的主要定位测量装置由加速度传感器和陀螺仪组成。其中,加速度传感器是用来测量载体所受到的惯性力,并通过牛顿第二加速度定律获取被测载…

OpenGL 面剔除

1.简介 OpenGL能够检查所有面向观察者的面,并渲染它们,而丢弃那些背向的面,节省我们很多的片段着色器调用(它们的开销很大!)。但我们仍要告诉OpenGL哪些面是正向面,哪些面是背向面。OpenGL使用…

Axure教程——走马灯

本文介绍用Axure中的动态面板制作走马灯效果 一、效果 预览地址:https://okjxsd.axshare.com 二、功能 1、图片自动播放并显示其状态 2、点击左右箭头,图片播放并显示其状态 三、制作 1、动态面板制作 拖进一个动态面板元件,设置尺寸&#…

RISC-V semi-hosting原理以及实践

嵌入式裸机调试需要在有限资源的目标硬件上尽可能挖掘更多的信息,比如打印寄存器等等,但是即便看似很简单的串口打印,在有的情况下也是奢望,针对这种情况,能够有效利用主机资源协同调试的semi-host(半主机&…

B. Fish Graph(dfs找环)

Problem - 1817B - Codeforces 给定一个具有n个节点和m条边的简单无向图。请注意,该图不一定是连通的。节点从1到n标记。 如果图包含具有特殊节点u的简单循环,则定义图为Fish Graph。除循环中的边之外,图应恰好有2条额外的边。两条边都应连接…

设计模式之外观模式笔记

设计模式之外观模式笔记 说明Facade(外观)目录外观模式示例类图电灯类电视机类空调类智能音箱外观类测试类 说明 记录下学习设计模式-外观模式的写法。JDK使用版本为1.8版本。 Facade(外观) 意图:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高…

【2023,学点儿新Java-23】初步了解Java中的修饰符:static及其作用、native特性、final的理解

前情回顾: 【2023,学点儿新Java-22】Java中package的作用是什么 | Java中import的用法 | Java中的权限修饰符:private、protected、public【2023,学点儿新Java-21】Java中default的语法格式 | 父类私有的方法能被重写吗&#xff…