【Git教程】(七)变基与拣取 —— 变基操作的概念、适用场景及其实现方式,拣取操作的实现 ~

Git教程 · 变基与拣取

  • 1️⃣ 工作原理:复制提交
  • 2️⃣ 避免“钻石链”
  • 3️⃣ 什么情况下会遇到冲突
  • 4️⃣ 移植分支
  • 5️⃣ 执行变基后原提交的情况
  • 6️⃣ 提交的原件与副本存在于同一版本库中所带来的问题
  • 7️⃣ 捡取
  • 🌾 总结

在这里插入图片描述

通常, 一段提交历史中往往都存在着许多杂乱的分支。Git 可以尽可能地帮助我们理顺这些历史记录。这里会用到的最重要的工具当然就是 rebase 命令了,它可以可以将某一次提交在提交图上产生的影响从一个节点转移到另一节点。

我们可以用该命令做以下几件事情。

  • 如果你不小心在错误的分支上执行了一次提交。例如你可能将一次 bug 修复提交到了 当前开发线(即 master 分支)上。
  • 当多个开发者在致力于开发同一软件时,他们会频繁地整合自己的修改。如果不进行 变基,他们可能会创建出一部带有多个小分支和分岔的历史(我们称之为钻石链)。 通过 rebase 命令,我们可以将其改造成一部较为平滑的线性历史。

1️⃣ 工作原理:复制提交

变基操作的工作原理很简单: Git 会让我们想要移动的提交序列在目标分支上按照相同的顺序重新再现一遍。这就相当于我们为各个原提交做了个副本,它们拥有相同的修改集、同一作者、日期以及注释信息。

请注意:乍看之下,好像 Git 只是在执行变基重操作时移动了相关提交。但事实上,这 些“被转移”的提交往往都是一些拥有不同提交散列值的新提交。了解这一情况非常重要,
尤其是在提交已经从原分支已经扩散到其子分支时。

由于新提交会被记录在提交图中的不同位置,所以当然有可能会引发冲突,因为其原本的修改未必适合当前的情况。对于这类修改,我们必须要通过手动来解决合并冲突。


2️⃣ 避免“钻石链”


在这里插入图片描述

如果为同一软件工作的若干个开发者频繁地归并各种修改,该项目所建立起来的提交历史看起来就会像一条钻石链。这时候我们可以利用变基操作将其整理成一部内容等效,但线性发展的历史。

下面,我们通过下图中的具体例子来看看变基操作的具体过程。如你所见,从 master 分支上岔出了一个名为 feature-a 的分支,其中包含了C 和 D 两个提交。同时, master 分支也得到了进一步的开发,于是多出了一个提交B。

在这里插入图片描述现在,你可以通过 git merge master 命令来合并这些修改,然后再用 rebase 命令理顺其
历史纪录。该命令需要一个参数,以说明我们要将活动分支上的最新修改纳入哪一个分支。

> #Branch "feature-a" is active
> git rebase master

在收到这个命令之后,Git就会去做以下事情,以便将活动分支(feature-a)融合到 master
分支上。

  • 确认涉及到哪些提交:Git会确认是要将活动分支 feature-a 上的哪一些目前不在目标分支 ( master) 上,在这里就是提交C 和 D。
  • 确认目标位置:Git 会确认目标提交的位置,该提交就是 master 上 feature-a 将要执行变基操作地方,在这里就是提交B。
  • 复制提交:以目标提交为基础重演上述提交中的所有修改,并相应创建提交 C’ 和 D’。
  • 将活动分支重置:活动分支将被移动到上述被复制提交的顶部,在这里就是提交D’。

然而在很多情况下,我们可能不会直接去调用 rebase 命令。相反,我们通常会用 pull 命令加上 --rebase 选项来对远程版本库中的修改进行变基处理。

注意:旧提交 C 和 D 偶尔还会留在版本库中,虽然它们已经不再直接可见,因为 feature-a 分支现在已经指向了 D’ 。但是,我们依然还是可以通过散列值对C 和 D 进行访问。 只有在用 gc 命令执行垃圾回收之后,它们才会真正从版本库中消失。


3️⃣ 什么情况下会遇到冲突

merge 命令一样,rebase 命令也会在相关修改不匹配的时候以冲突的形式被终止。 但它们之间有个重要的区别:即在合并过程中,我们得到的是两个分支合体之后的单一提交结果。而在变基过程中,我们是在依次执行重复的若干次提交。如果一切顺利,其最后一次所提交的内容应该会与其执行 merge 命令时的结果相同,因为 Git 在这两个命令中采用 了相同的冲突解决算法。但如果 rebase 命令在执行过程中遇到冲突情况,该命令进程就会被打断,相关文件中也会出现冲突标志。我们需要先手动或通过合并工具对文件进行清理, 并重新将它们添加到暂存区中。然后再执行 rebase 命令加 --continue 选项,从该点继续之前的进程。

> git add foo.txt
> git add bar.txt
> git rebase --continue

当然,我们也可以用 --abort 选项取消这次的 rebase 命令,或者用 --skip 选项跳过引起冲突的提交。这样该次提交就被直接忽略,其中的修改将不会出现在新分支上。

需要特别注意,与合并操作不同的是,在被中断变基作业的那些提交副本中可能已经有一部分被执行变基操作了。


4️⃣ 移植分支

有时候,在已经创建了一个分支,并完成其首次提交的情况下,我们也可以通过 --onto
选项将该分支移植到提交图中的另一个位置上。
在下面的例子中, feature-a 分支被移植到了release1 分支上。

在这里插入图片描述

> #Branch "feature-a" is active
> git rebase master --onto release1

在这里, rebase 命令的第一个参数所指定的是原分支(即这里的 master 分支)。然后,
Git 就会去确认活动分支(即 feature-a) 上所有不属于原分支的所有提交(在这里就是提交E 和 F) 。 然后通过--onto 选项将这些提交拷贝到指定位置上(即这里的 release1 分支)。

某一分支已经被移动到了提交图中的另一位置上。

  1. 在必要情况下,我们可以切换到待移动的分支上
    git checkout the-branch
  2. 确定原位置
    即原分支,相关分支是从这里被移出去的。Git会将其中所有不属于原分支的提交移出来。
  3. 检查所要移动的内容
    提前对可能会受到影响的提交做个相应的检查是一个明智的选择,因为一个变基操作错误可能会给版本库带来一个非常混乱的局面。
    git log origin..the-branch
  4. 确定目标位置
    选择一个分支来充当被移动分支执行变基操作的目标位置。
  5. 执行变基操作
    git rebase origin --onto target

注意: rebase 命令中的原位置并不一定非得是一个分支。它也可以是任何提交。


5️⃣ 执行变基后原提交的情况

这些提交会在变基过程中被复制。但其原件(即本例中的提交C 和 D) 依然还可以通过散列值来进行访问,如图所示。通常情况下,当没有分支可以进一步从这些提交中继续发展时,下一轮垃圾收集过程(通过 gc 命令)就会直接将它们从版本库中删除。

在这里插入图片描述


6️⃣ 提交的原件与副本存在于同一版本库中所带来的问题

重复容易造成版本库中的混乱。它们可以很容易引起误解,让人以为某段既定的代码修 改包含在哪一分支上,不包含在哪一分支上。通常来说,git log HEAD..a-branch 显示的是在a-branch 上而不在当前分支的那些提交。如果存在重复的话,当前分支也可能已经包含了该代码的修改。这会增加审查以及质量保证方面的复杂性。

除此之外,这种重复还有可能会给我们稍后对带有重复提交的分支与带有原始提交的分 支之间的合并带来麻烦。在最好的情况下,Git会自己识别出同样的修改出现了不止一次,并对其只采用一次。而在最坏的情况下,如果该重复提交被当作冲突来处理, Git 是无法检测到的,然后它会试图多次采用这一修改。结果就会产生一些令用户意外的冲突。

一旦我们将某次提交传递给了一个远程版本库,就不应该再用 rebase 命令来移动该提交了。否则,由于其他开发者可能会在其原作上继续他们的工作,这在将来再次合并修改的时候一定会带来问题。


7️⃣ 捡取

接下来,我们再来介绍另一种复制提交的方式: cherry-pick 命令。我们可以用它来指定自己需要的提交,Git 会为此创建一次新的提交,该提交中会拥有相同的修改集与当前分支中的元数据。

> git cherry-pick 23ec70f6b0

那么对于捡取操作,我们应该了解哪些事情呢?

  • cherry-pick 不会参考历史纪录。因而 mergerebase 还可以被正确地识别成文件的 重命名与移动操作, cherry-pick 则不能。
  • 捡取操作有时候会被用来将一些小bug 的修复传递到各种不同的发行版中。
  • 该操作的另一种应用是从即将删除的分支中转移出有用的提交。
  • 警告:捡取操作也有可能会引发我们之前所说的重复提交问题。

🌾 总结

  • 变基操作:Git 能将提交复制到提交图中的其他地方。尽管其中的修改与元数据(作者、日期)将保持不变,但该复制结果会有一个新的提交散列值。你可以通过rebase 命令以多种方式对提交图进行重构。
  • 只适用于推送之前:通常情况下,我们应该只对那些还未被传递给其他版本库的提交试用rebase 命令。否则,这样做可能给日后带来非常麻烦的合并冲突。
  • 理顺历史:如果我们在并行式开发的过程中使用merge 命令解决了其中的冲突,就会得到一部经历了多次分岔与合并的历史。如果用rebase 来代替 merge, 我们就会得到一部呈线性发展的历史。
  • 变基过程中的冲突:Git 会逐段逐段重演被复制的提交。如果因为某些修改与工作区内容不相符而引发了冲突,变基的进程就会被中断。与执行 merge 命令的过程一样, 开发者可以先手动解决掉冲突,再继续变基的过程。
  • rebase --onto :通过该选项,我们可以将某一分支移动到提交图中另一个完全不同的位置。


温习回顾上一篇(点击跳转)
《【Git教程】(六)分支合并 —— 合并过程,各类合并冲突及解决思路 ~》

继续阅读下一篇(点击跳转)
《》

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

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

相关文章

Centos中安装Docker及Docker的使用

在centos7系统中安装指定版本的docker,并通过docker使用安装mysql为例,阐述docker的使用。 2.1、Docker卸载及安装yum依赖 【卸载Docker,如果安装的Docker的版本不合适】 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-…

自定义类型详解(下)

2.位段 2.1 什么是位段 位段的声明和结构是类似的,有两个不同: 1. 位段的成员必须是 int 、 unsigned int 或 signed int 。 2. 位段的成员名后边有一个冒号和一个数字。 比如: struct A {int _a:2;int _b:5;int _c:10;int _d:30; …

继续预训练对大语言模型的影响

翻译自文章:Investigating Continual Pretraining in Large Language Models: Insights and Implications 摘要 本文研究了大型语言模型(LLMs)中不断学习(CL)的不断发展领域,重点是制定有效和可持续的训练…

大屏可视化组态工具

推荐一个包含2D、3D、图表、动态交互、数据管理等一体的大屏可视化组态工具:乐吾乐大屏可视化。 1 简介 乐吾乐大屏可视化,零代码实现物联网、工业智能制造等领域的可视化大屏、触摸屏端UI以及工控可视化的解决方案。同时也是一个Web组态工具&#xff…

基于 ECharts的Python 数据可视化库,它允许用户使用 Python 语言生成各种类型的交互式图表和数据可视化

pyecharts 是一个基于 ECharts 的 Python 数据可视化库,它允许用户使用 Python 语言生成各种类型的交互式图表和数据可视化。 ECharts 是由百度开发的一款强大的开源数据可视化库,而 Pyecharts 则是 ECharts 的 Python 封装,使得在 Python 中…

javaweb学习(day04-XML)

一、介绍 1 官方文档 地址: https://www.w3school.com.cn/xml/index.asp 2 为什么需要 XML 需求 1 : 两个程序间进行数据通信需求 2 : 给一台服务器,做一个配置文件,当服务器程序启动时,去读取它应当监听的端口号、还有连接数据库的用户名…

1.3 vue ui框架-element-ui框架

1 前言 ElementUI是一套基于VUE2.0的桌面端组件库,ElementUI提供了丰富的组件帮助开发人员快速构建功能强大、风格统一的页面。 ElementUI官网 https://element.eleme.io 2 安装 运行命令 cnpm i element-ui -S -S表示只在该项目下安装,不是全局安…

JavaWeb之 创建 Web项目,使用Tomcat 部署项目,使用 Maven 构建Web项目(一万八千字详解)

目录 前言3.1 Tomcat 简介3.1.1 什么是 Web服务器3.1.2 Tomcat 是什么3.1.3 小结 3.2 Tomcat 的基本使用3.2.1 下载 Tomcat3.2.2 安装 Tomcat3.2.3 卸载 Tomcat3.2.4 启动 Tomcat3.2.5 关闭 Tomcat3.2.6 配置 Tomcat3.2.7 在 Tomcat 中部署 Web项目 3.3 在 IDEA 中创建 Web 项目…

C#使用iText7给PDF文档添加书签

上一篇文章将SqlSugar官网文档中每个链接对应的网页生成独立PDF文档再合并为单个PDF文档,但是没有书签,八百多页的内容查找和跳转都不方便,本文学习和使用iText7给PDF文档添加多级书签。   添加多级书签分为两大步骤:1&#xff…

Nodejs+vue汽车保养美容管理系统vscode前后端分离项目

汽车美容保养管理系统后台采用nodejs语言开发,前台页面和后台管理页面使用vue等技术开发,使用MySql作为数据持久化存储工具对汽车美容保养管理系统的用户等角色权限对应的功能等进行存储。采用vsocde集成IDE对汽车美容保养管理系统统进行开发,整合系统的各个模块。 拟开发的汽车…

对el-table表格的表头操作

效果1:单层表头合并 图示1: 说明: header-cell-style函数用于给表头添加样式,其返回的值会被添加到表头对应样式中去注意函数的形参中的column.id为单元格的class类大家最好打印一下,结合审查dom看类名 代码&#x…

Springboot项目中定时任务的四种实现方式

文章目录 1. 使用Scheduled注解1.1 时间间隔执行1.2 固定时间点执行 2. 使用EnableScheduling注解启用定时任务3. 实现SchedulingConfigurer接口4. 使用Quartz框架4.1 配置QuartzScheduler4.2 定义Job类和Trigger类 5. 总结 在开发现代应用时,定时任务是一个非常常见…