git merge 和 git rebese的区别

news2024/10/7 6:45:55

git merge 和 git rebese的区别

拉取分支和合并代码会涉及两种选择,git merge 和 git rebase:

  • rebase:变基,会有一个干净的分支,但是对于记录来源不够清楚
  • merge:合并,git 分支看起来比较混乱,但是清楚各个记录的来源和时间点。

推荐使用 merge:

  1. 拉取公共分支使用最新代码:merge。rebase,也就是 git pull - rgit pull --rebase。这样的好处是,提交记录比较简洁。但有个缺点就是 rebase以后就不知道当前的分支最早从哪个分支拉出来了,因为基底变了。
git pull -r
git pull --rebase
  1. 往公共分支上合并代码 merge,如果使用 rebase,那么其它开发人员想看主分支的历史,就不是原来的历史了,历史已经被篡改了。举个例子解释下,比如张三和李四从共同的节点拉出来开发,张三先开发完提交了两次然后merge上去了,李四后来开发完如果rebase上去(注意,李四需要切换到自己本地的主分支,假设先pull了张三的最新改动下来,然后执行<git rebase 李四的开发分支>,然后再git push到远端),则李四的新提交变成了张三的新提交的新基底,本来李四的提交是最新的,结果最新的提交显示反而是张三的,就乱套了,以后有问题就不好追溯了。
  2. 正因如此,大部分公司其实会禁用rebase,不管是拉代码还是push代码统一都使用merge,虽然会多出无意义的一条提交记录“Merge … to …”,但至少能清楚地知道主线上谁合了的代码以及他们合代码的时间先后顺序。

git rebase

过程详解

首先我们通过简单的提交节点图解感受一个rebase

  1. 构造两个分支 master 和 feature,其中feature是在提交点B处从master上拉出来分支
  2. master上有一个新提交 M,feature上有两个新提交 C 和 D

img

此时我们切换到feature分支上,执行rebase命令,相当于是想要把master分支合并到feature分支(这一步场景就可以类比为我们在自己的分支上开发了一段时间,准备从主干 master 上拉一下最新改动。模拟了 git pull --rebase的情形)

# 将 master 上的分支合并到feature
# 这两条命令等价于 git rebase master feature
git checkout feature
git rebase master

下面为变基后的提交节点,解释一下其工作原理:

img

  • feature:待变基分支、当前分支
  • master:基分支,目标分支

官方解释:当执行rebase操作时,git 会从两个分支的共同祖先开始提取待变基分支上的修改,然后待变基分支指向基分支的最新提交,最后将刚才提交的修改应用到基分支的最新提交的后面。

结合demo解释:当在feature分支上执行git rebase master时,git会从 master 和 feature 的共同祖先 B 开始提取feature分支上的修改,也就是 C 和 D 两个提交,先提取到。然后将 feature 分支指向 master 分支的最新提交上,也就是 M。最后把提取的 C 和 D 接到 M 后面,注意这里的接法,官方没有说清楚,实际上是依次拿 M 和 C、D的内容分别比较,处理冲突后生成新的 C 和 D。一定注意,这里新C、D和之前的C、D已经不一样了,是我们处理冲突后的新内容,feature 指针自然最后也是指向D。

通俗解释,rebase,变基,可以直接理解为改变基底。feature 分支是基于 master 分支的B拉出来的分支,feature 的基底是B。而 mater 在 B之后有新的提交,就相当于此时要用 master 上的新的提交来作为 feature分支的新基底。实际操作为把B之后feature的提交先暂存下来,然后删掉原来的提交,再找到 mater 的最新提交位置,把存下来的提交再接上去(接上去是逐个和新基底处理冲突的过程),如此feature分支的基底就相当于变成了M而不是原来的B了。(注意,如果master上在B以后没有新提交,那么就还是用原来的B作为基,rebase操作相当于无效,此时和git merge就基本没区别了,差异只在于git merge会多一条记录merge操作的提交记录)

工作场景

上面的例子可抽象为如下实际工作场景:远程库上有一个 master 分支目前开发到B了,张三从B拉了代码到本地的feature分支进行开发,目前提交了两次,开发到D了,李四也从B拉到本地的master分支,他提交到了M,然后合到远程库的master上了,此时张三想从远程库master拉下最新代码,于是他在feature分支上执行了git pull origin master:feature --rebase(注意要加-rebase参数),即把远程库master分支给rebase下来,由于李四更早开发完,此时远程master上是李四的最新内容,rebase后再看张三的历史提交记录,就相当于是张三是基于李四的最新提交M进行的开发了。(但实际上张三更早拉代码下来,李四拉的晚但提交早)

git merge

git merge有好几种不同的模式。

git merge是开发者做常用的 git 命令之一,默认情况下你直接使用 git merge 命令,没有附加任何选项命令的话,那么应该是交给 git 来判断使用哪种 merge 模式,实际上 git 默认执行的指令是 git merge -ff 指令(默认值)。

对于专业的开发者来说,你可能无须每次合并都指定合并模式(如果需要的话还是要指定的),但是你可能需要知道 git 在背后为你默认做了事情,这样才能保证你的代码万无一失。

fast-forward(–ff):master与feature存在公共祖先

开发者小王接到需求任务,从 master 分支中创建功能分支,git 指令如下:

git checkout -b feature556
Switched to a new branch 'feature556'

小王在 feature556 分支上完成的功能开发工作,然后产生1次 commit,

git commit -m 'Create pop up effects'
[feature556 6104106] create pop up effects
3 files changed, 75 insertions(+)

我们再更新一下 README 自述文件,让版本差异更明显一些

git commit -m `updated md`

这时候我们看看当前分支的 git 历史记录,输入 git log --online -all 可以看到全部分支的历史线:

f2c9c7f (HEAD -> feature556) updated md
6104106 create pop up effects
a1ec682 (origin/main, origin/HEAD, main) import dio
c5848ff update this readme
8abff90 update this readme

功能完成后自然要上线,我们把代码合并,完成上线动作,代码如下:

git checkout master
git merge feature556
Updating a1ec682..38348cc
Fast-forward
  .......  | 2+++
 1 file changed, 2 insertions(+)

如果你注意上面的文字,你会发现 git 帮我们自动执行了 Fast - forward 操作,那什么是 Fast - forward?

Fast-forward 是指 Mater 合并了 Feature 时候发现 Master 当前节点一直和 Feature 的根节点相同,没有发生改变,那么 Master 快速移动头指针到 Feature 的位置,所以 Fast-forward并不会发生真正的合并,只是通过移动指针造成合并的假象,这也体现了 git 设计的巧妙之处。合并后的分支指针如下:

在这里插入图片描述

通常功能分支(feature556)合并master后会被删除,通过下图可以看到,通过Fast-forward模式产生的合并可以产生干净并且线性的历史记录:

在这里插入图片描述

non-Fats-forward(-no-ff):master与feature不存在公共祖先

什么时候会产生 non-Fast-forward,通常,当合并的分支跟master不存在共同祖先节点的时候,这时候在 merge 的时候 git 默认无法使用 Fast-forward模式。

在这里插入图片描述

可以看到master分支已经比feature001快了2个版本,master已经没办法通过移动头指针来完成Fast-forward,所以在master合并feature001的时候就不得不做出真正的合并,真正的合并会让 git 多做很多工作,具体合并的动作如下:

  • 找出master和feature001的公共祖先,节点c1,c6,c3三个节点的版本(如果有冲突需要处理)
  • 创建新的节点c7,并且将三个版本的差异合并到c7,并且创建commit
  • 将master和HEAD指针移动到c7

补充🏡:大家在 git log 看到很多类似:Merge branch 'feature001' into master 的 commit 就是 non-Fast-forward 产生的。
执行完以上动作,最终分支流程图如下:

在这里插入图片描述

fast-forward only(-ff-only):尝试-ff方式合并,如果不满足则退出

先简单介绍一下 git merge 的三个合并参数模式:

  • -ff 自动合并模式:当合并的分支为当前分支的后代的,那么会自动执行 --ff (Fast-forward) 模式,如果不匹配则执行 --no-ff(non-Fast-forward) 合并模式
  • –no-ff 非 Fast-forward 模式:在任何情况下都会创建新的 commit 进行多方合并(及时被合并的分支为自己的直接后代)
  • –ff-onlu Fast-forward 模式:只会按照 Fast-forward 模式进行合并,如果不符合条件(并非当前分支的直接后代),则会拒绝合并请求并且退出

三种模式的选择

三种merge模式没有好坏和优劣之分,只有根据需求和实际情况选择合适的合并模式才是最优解

  • 如果你是小型团队,并且追求干净线性 git 历史记录,那么我推荐使用 git merge --ff-only 方式保持主线模式开发是一种不错的选择

  • 如果你团队不大不小,并且也不追求线性的 git 历史记录,要体现相对真实的 merge 记录,那么默认的 git --ff 比较合适

  • 如果你是大型团队,并且要严格监控每个功能分支的合并情况,那么使用 --no-ff 禁用 Fast-forward 是一个不错的选择

区别及推荐

区别

rebase:变基,会有一个干净的分支,但是对于记录来源不够清晰,commit的提交先后顺序也会比较错乱。(rebase以后我就不知道我的当前分支最早是从哪个分支拉出来的了,因为基底变了)

img

merge(推荐使用):合并,git分支看起来比较混乱,但是清楚各个记录的来源与时间节点

在这里插入图片描述

推荐:全部使用merge

拉公共分支使用最新代码:merge;有些公司会要求使用rebase,也就是git pull -r或git pull --rebase。这样的好处很明显,提交记录会比较简洁。但有个缺点就是rebase以后我就不知道我的当前分支最早是从哪个分支拉出来的了,因为基底变了嘛,所以看个人需求了。总体来说,即使是单机也不建议使用。

git fetch
git merge --ff-only

往公共分支上合代码merge;如果使用rebase,那么其他开发人员想看主分支的历史,就不是原来的历史了,历史已经被你篡改了。举个例子解释下,比如张三和李四从共同的节点拉出来开发,张三先开发完提交了两次然后merge上去了,李四后来开发完如果rebase上去(注意,李四需要切换到自己本地的主分支,假设先pull了张三的最新改动下来,然后执行<git rebase 李四的开发分支>,然后再git push到远端),则李四的新提交变成了张三的新提交的新基底,本来李四的提交是最新的,结果最新的提交显示反而是张三的,就乱套了,以后有问题就不好追溯了。

正因如此,大部分公司其实会禁用rebase,不管是拉代码还是push代码统一都使用merge,虽然会多出无意义的一条提交记录“Merge … to …”,但至少能清楚地知道主线上谁合了的代码以及他们合代码的时间先后顺序。

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

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

相关文章

Linux 调度优先级

Linux中的每个任务都有其优先级。这个优先级的范围从-20到19。优先级越低&#xff08;-20&#xff09;&#xff0c;分配 给任务的CPU时间就越多。默认的优先级是0。 并非所有的任务都需要使用相同的优先级。交互式应用要求快速响应&#xff0c;通过 crontab 运行的后台…

半导体行业的隐形翅膀:国产RFID技术突破封锁,助力生产

半导体行业的隐形翅膀&#xff1a;国产RFID技术突破封锁&#xff0c;助力生产 RFID技术&#xff0c;简单来说&#xff0c;就是一种自动识别技术&#xff0c;通过无线电波实现对标签信息的读取和写入。而这些标签&#xff0c;就像给物品贴上的小标签&#xff0c;上面存储着它们…

Windows主机入侵检测与防御内核技术深入解析

第2章 模块防御的设计思想 2.1 执行与模块执行 本章内容为介绍模块执行防御。在此我将先介绍“执行”分类&#xff0c;以及“模块执行”在“执行”中的位置和重要性。 2.1.1 初次执行 恶意代码&#xff08;或者行为&#xff09;要在被攻击的机器上执行起来&#xff0c;看起…

测试架构师必备技能-Nginx安装部署实战

Nginx(“engine x”)是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的免费开源Web和 反向代理服务器&#xff0c;也是一个 IMAP/POP3/SMTP 代理服务器。在高并发访问的情况下&#xff0c;Nginx是Apache服务器不错的替代品。官网数据显示每秒TPS高达50W左右。本文为读者朋…

PHP项目搭建与启动

1、拉取项目 2、安装phpstudy 下载地址&#xff1a; Windows版phpstudy下载 - 小皮面板(phpstudy) (xp.cn) 软件安装&#xff1a; Apache2.4.39、Nginx1.15.11、MySQL8.0.12、 composer2.5.8 添加伪静态 将下面代码写入到伪静态配置文本域框内&#xff1a; location ~* (ru…

SD-WAN怎样助力企业网络升级

随着企业规模的持续扩张&#xff0c;其网络建设的重要性日益凸显&#xff0c;成为业务成功的基石。尤其对于中小企业而言&#xff0c;信息化和电脑化已成为推动生产力和竞争力提升的关键所在。办公室自动化、数据库、ERP、CRM、物流供应链等关键业务应用的不断增加&#xff0c;…

Windows下Golang初学乍到

安装 没啥说的&#xff0c;官网下载即可&#xff0c;地址&#xff1a;All releases - The Go Programming Language 根据系统类型下载即可&#xff01; 配置 Windows下安装完后&#xff0c;发现path中已经有了&#xff0c;但为了避免可能的问题&#xff0c;还是建议配置GOPA…

pwn | BUUCTF rip 1 pwn基本思路

题目&#xff1a;BUUCTF rip 1 整体参考&#xff1a; 添加链接描述&#xff08;写得好详细我好爱 BUUCTF (PWN) RIP详细分析&#xff08;为什么payload有两种写法 其他知识&&引用&#xff1a; 二进制的保护机制 8086汇编语言dup指令学习 【Tips】使用gdb-peda进行RIP覆…

java 词法分析练习

import parser.Parser;import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class Main {public static void main(String[] args) {// 关键词List<String> keyList new ArrayList<>(Arrays.asList("int","String…

Android --- 网络请求

通常在 Android 中进行网络连接一般使用 Scoket 和HTTP&#xff0c;HTTP 请求方式比 Scoket 多。HTTP 请求一般采用原生的 HttpClient 和 HttpUrlConnection 的两种网络访问方式&#xff08;系统自带的&#xff09;。但是在 Android 5.0 的时候 Google 就不推荐使用 HttpClient…

力扣--N皇后

题目: 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。…

免费预约即将截止,5月7日上海TCT亚洲3D打印展参观指南,收藏!

进入TCT亚洲展官网&#xff08;网页搜索TCT亚洲展&#xff09;&#xff0c;免费登记预约 2024年TCT亚洲展作为推动增材制造在亚洲市场的业务交流的重要平台&#xff0c;将于2024年5月7日至9日在国家会展中心&#xff08;上海&#xff09;7.1&8.1馆举办&#xff0c;与海内外…

【LAMMPS学习】八、基础知识(4.4)TIP4P水模型

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

软件测试面试笔试题-选择题(物联网)

1.在软件生命周期中&#xff0c;测试人员从那个阶段开始参与更有利于软件项目的成功() a)需求分析阶段 b)设计阶段 c)编码阶段 d)系统测试阶段 2.在 Bugzilla 缺陷跟踪系统中&#xff0c;下列选项中属于缺陷状态的是( )(选两项) a) new b) fixed clater d) verified 3.在 Bug…

一文解读:阿里云 AI 基础设施的演进与挑战

云布道师 2024 年 4 月 18-19 日&#xff0c;2024 中国生成式 AI 大会在北京 JW 万豪酒店举行&#xff0c;阿里云高级技术专家、阿里云异构计算 AI 推理团队负责人李鹏受邀在【AI Infra】专场发表题为《AI 基础设施的演进与挑战》的主题演讲。李鹏从 AIGC 对云基础设施的挑战、…

ProTable/EditableProTable修改表单保存后刷新界面数据不更新

1.背景 大坑。编辑表格保存后&#xff0c;接口拿到最新表格数据&#xff0c;但是界面没有刷新。本以为是加个id给表格就能刷新的&#xff0c;没想到需要重置表单。 2.解决 表格数据变更后需要重置表单 form.resetFields() <ProTablecolumns{columns}rowKey"id"…

OSPF域间路由

注&#xff1a;区域&#xff08;area&#xff09;是以接口进行划分的 描述&#xff1a; R1的g0/0/1接口属于area 0 √ R1属于区域0和区域1 1.设计原则 1、OSPF区域的设计原则&#xff1a; 骨干区域有且只能存在一个 非骨干区域必须和骨干区域相连 多区域时&#…

uniapp app权限说明弹框2024.4.23更新

华为上架被拒绝 用uni-app开发的app&#xff0c;上架华为被拒&#xff0c;问题如下&#xff1a; 您的应用在运行时&#xff0c;未见向用户告知权限申请的目的&#xff0c;向用户索取&#xff08;电话、相机、存储&#xff09;等权限&#xff0c;不符合华为应用市场审核标准。…

鸿蒙ArkUI实战开发-如何通过上下滑动实现亮度和音量调节

场景说明 在音视频应用中通常可以通过上下滑动来调节屏幕亮度和音量大小&#xff0c;本例即为大家介绍如何实现上述UI效果。 说明&#xff1a; 由于当前亮度和音量调节功能仅对系统应用开发&#xff0c;所以本例仅讲解UI效果的实现。 效果呈现 本例效果如下&#xff1a; 当在…

【Redis 开发】一人一单,超卖问题(悲观锁,乐观锁,分布式锁)

锁 悲观锁乐观锁第一种&#xff1a;版本号法第二种&#xff1a;CAS法实现乐观锁 悲观锁与乐观锁的比较 一人一单分布式锁Redis实现分布式锁 悲观锁 认为线程问题一定会发生&#xff0c;因此在操作数据库之前先获取锁&#xff0c;确保线程串行执行&#xff0c;例如Synchronized…