图解Git——变基《Pro Git》

news/2025/1/21 18:24:22/文章来源:https://www.cnblogs.com/cikiss/p/18684140

变基

1. 变基的由来

  1. 回顾之前分支合并
    1. 分叉的提交历史

      编辑

    2. 通过合并操作来整合分叉的历史

      编辑

  1. 有一种方法:你可以提取在 C4 中引入的补丁和修改,然后在 C3 的基础上应用一次。 在 Git 中,这种操作就叫做 变基(rebase)。 你可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样。

2. 变基的基本操作

  1. 切换到想要变基的分支:git checkout experiment
  2. 变基:git rebase master

3. 变基的原理

编辑

  1. 确定共同祖先:Git 首先寻找 experiment 分支和 master 分支的共同祖先提交,此例中为 C2,因为 experiment 分支从 C2 处分叉。
  2. 保存提交序列:Git 把 experiment 分支上从共同祖先 C2 之后的提交(即 C4)保存成一个序列。这些提交记录了 experiment 分支相对共同祖先的变化。
  3. 调整分支基础:Git 将 experiment 分支的指针移开,把它的基础设置为 master 分支的最新提交 C3。这一步为后续重新应用提交做准备,让 experiment 分支基于 master 分支的最新状态。
  4. 生成新提交:Git 依照保存的提交序列,将 C4 重新应用到新基础 C3 上。通过模拟 C4C3 基础上的变更效果,Git 创建一个新的提交对象 C4'。由于 C4' 的父提交是 C3(而原 C4 的父提交是 C2),尽管功能效果与 C4 相同,但它是一个全新的提交,拥有不同的哈希值。
  5. 过程图:
    1. 变基后:

      编辑

    2. 回到 master 分支,并进行一次快进合并后:

      编辑


4. 更复杂的变基应用——对两个分支进行变基(git rebase --onto <newbase> <upstream> [branch]

  1. git rebase --onto <newbase> <upstream> [branch]命令格式:
    1. <newbase>:新的基底
      1. 意义: 指定你希望“重放的提交”应用到的目标分支或提交。
      2. 作用: 这些提交会被重放到 <newbase> 指定的位置。
      3. 类型:
        1. 可以是分支名(如 master)。
        2. 可以是提交哈希(如 abc123)。
        3. 可以是一个引用(如 HEAD~2)。
    1. <upstream>:基准分支
      1. 意义: 确定从哪里开始选取要重放的提交。
      2. 作用: Git 会找到 <upstream>[branch] 的共同祖先,并选取从这个分叉点到 [branch] 之间的提交进行“重放”。
      3. 类型:
        1. 分支名(如 dev)。
        2. 提交哈希。
        3. 可以省略,默认使用 [branch] 的上游分支(即用 git branch --set-upstream-to 设置的分支)。
    1. [branch]:当前分支 :
      1. 意义: 指定操作的分支,默认为当前分支。
      2. 作用: 表示重放哪个分支的提交。
      3. 类型:
        1. 分支名(如 feature)。
        2. 如果省略,则默认使用当前所在的分支。
  1. 模拟你创建了一个主题分支 server,为服务端添加了一些功能,提交了 C3C4。 然后从 C3 上创建了主题分支 client,为客户端添加了一些功能,提交了 C8C9。 最后,你回到 server 分支,又提交了 C10

    编辑

  2. 截取主题分支上的另一个主题分支,然后变基到其他分支:

    1. 假设你希望将 client 中的修改合并到主分支并发布,但暂时并不想合并 server 中的修改。

    2. 这时使用 git rebas 命令的 --onto选项,选中在 client 分支里但不在 server 分支里的修改(即 C8C9),将它们在 master 分支重放:git rebase --onto master server client

    3. 翻译一下这个命令: “取出 client 分支,找出它从 server 分支分歧之后的补丁, 然后把这些补丁在 master 分支上重放一遍,让 client 看起来像直接基于 master 修改一样”。这理解起来有一点复杂,不过效果非常酷。

    4. 编辑

    5. 快进合并 master,使之包含来自 client 分支的修改

      1. git checkout master + git merge client

      2. 快进合并后:

        编辑

  1. server 中的修改变基到 master 上—— $ git rebase master server
    1. git rebase <basebranch> <topicbranch>简化了先切换到 server分支,再对其执行变基。

    2. server 变基后:

      编辑

  1. 最终的历史提交并删除 clientserver 分支
    1. 快进合并主分支 mastergit checkout master + git merge server

    2. 删除 clientserver 分支:git branch -d client + git branch -d server

    3. 最终的提交历史:

      编辑


5. 变基的风险

奇妙的变基也并非完美无缺,要用它得遵守一条准则:

如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。(

  • 如果你的提交已经被其他开发者获取并使用,避免用 rebase 改变历史。
  • 使用 rebase 的原则是: 只能在自己控制的范围内操作 ,避免影响其他人。)

如果你遵循这条金科玉律,就不会出差错。 否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。

变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。 如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你还要拉取并整合他们修改过的提交,事情就会变得一团糟。

5.1. 变基问题示例

让我们来看一个在公开的仓库上执行变基操作所带来的问题。 假设你从一个中央服务器克隆然后在它的基础上进行了一些开发。 你的提交历史如图所示:

编辑

Figure 44. 克隆一个仓库,然后在它的基础上进行了一些开发

然后,某人又向中央服务器提交了一些修改,其中还包括一次合并。 你抓取了这些在远程分支上的修改,并将其合并到你本地的开发分支,然后你的提交历史就会变成这样:

编辑

Figure 45. 抓取别人的提交,合并到自己的开发分支

接下来,这个人又决定把合并操作回滚,改用变基;继而又用 git push --force 命令覆盖了服务器上的提交历史。 之后你从服务器抓取更新,会发现多出来一些新的提交。

编辑

Figure 46. 有人推送了经过变基的提交,并丢弃了你的本地开发所基于的一些提交

结果就是你们两人的处境都十分尴尬。 如果你执行 git pull 命令,你将合并来自两条提交历史的内容,生成一个新的合并提交,最终仓库会如图所示:

编辑

Figure 47. 你将相同的内容又合并了一次,生成了一个新的提交

此时如果你执行 git log 命令,你会发现有两个提交的作者、日期、日志居然是一样的,这会令人感到混乱。 此外,如果你将这一堆又推送到服务器上,你实际上是将那些已经被变基抛弃的提交又找了回来,这会令人感到更加混乱。 很明显对方并不想在提交历史中看到 C4C6,因为之前就是他把这两个提交通过变基丢弃的。

5.2. 用变基解决变基

如果你 真的 遭遇了类似的处境,Git 还有一些高级魔法可以帮到你。 如果团队中的某人强制推送并覆盖了一些你所基于的提交,你需要做的就是检查你做了哪些修改,以及他们覆盖了哪些修改。

实际上,Git 除了对整个提交计算 SHA-1 校验和以外,也对本次提交所引入的修改计算了校验和——即 “patch-id”。

如果你拉取被覆盖过的更新并将你手头的工作基于此进行变基的话,一般情况下 Git 都能成功分辨出哪些是你的修改,并把它们应用到新分支上。

举个例子,如果遇到前面提到的 有人推送了经过变基的提交,并丢弃了你的本地开发所基于的一些提交 那种情境,如果我们不是执行合并,而是执行 git rebase teamone/master, Git 将会:

  • 检查哪些提交是我们的分支上独有的(C2,C3,C4,C6,C7)
  • 检查其中哪些提交不是合并操作的结果(C2,C3,C4)
  • 检查哪些提交在对方覆盖更新时并没有被纳入目标分支(只有 C2 和 C3,因为 C4 其实就是 C4')
  • 把查到的这些提交应用在 teamone/master 上面

从而我们将得到与 你将相同的内容又合并了一次,生成了一个新的提交 中不同的结果,如图 在一个被变基然后强制推送的分支上再次执行变基 所示。

编辑

Figure 48. 在一个被变基然后强制推送的分支上再次执行变基

要想上述方案有效,还需要对方在变基时确保 C4'C4 是几乎一样的。 否则变基操作将无法识别,并新建另一个类似 C4 的补丁(而这个补丁很可能无法整洁的整合入历史,因为补丁中的修改已经存在于某个地方了)。

在本例中另一种简单的方法是使用 git pull --rebase 命令而不是直接 git pull。 又或者你可以自己手动完成这个过程,先 git fetch,再 git rebase teamone/master

如果你习惯使用 git pull ,同时又希望默认使用选项 --rebase,你可以执行这条语句 git config --global pull.rebase true 来更改 pull.rebase 的默认配置。

如果你只对不会离开你电脑的提交执行变基,那就不会有事。 如果你对已经推送过的提交执行变基,但别人没有基于它的提交,那么也不会有事。 如果你对已经推送至共用仓库的提交上执行变基命令,并因此丢失了一些别人的开发所基于的提交, 那你就有大麻烦了,你的同事也会因此鄙视你。

如果你或你的同事在某些情形下决意要这么做,请一定要通知每个人执行 git pull --rebase 命令,这样尽管不能避免伤痛,但能有所缓解。

6. ⭐变基总结

  1. 什么是变基:
    • 将一系列提交“重新播放”到另一个分支上,改变提交历史,使其更线性。
  1. 基本操作:
    • git rebase <目标分支>:将当前分支的修改基于目标分支重新应用。
    • git rebase --onto <新基底> <旧基底> <分支>:将特定提交从旧基底移动到新基底。
  1. 优点:
    • 提交历史更加整洁、直线化。
    • 避免了不必要的合并提交,便于代码审查。
  1. 风险:
    • 如果变基已推送的提交,可能破坏其他开发者的工作(引发冲突和混乱)。
  1. 使用建议:
    • 可以使用: 对未推送的本地分支清理历史,或整理提交后再推送。
    • 避免使用: 对已共享的公共分支执行变基。
  1. 常用配置:
    • 默认拉取使用变基:git config --global pull.rebase true
  1. 注意事项:
    • 若必须在公共分支变基,请通知团队使用 git pull --rebase
    • rebase 是一种改写历史的操作,改写的历史如果已经被其他人使用,会造成混乱。

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

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

相关文章

1.21 javaweb学习

今天学习了html中onsubmit的使用 onsubmit事件处理器是专门用于表单(form)的提交事件,所以要注意div标签是不能直接使用onsubmit的 今天在作业项目中出现了这样的问题,将onsubmit放在了div标签中,导致数据无法被正常处理,上传数据有误,修改至form后问题解决 修改前数据提…

思通数科舆情系统的分析报告主要内容及其市场价值探析

思通数科舆情系统的分析报告广泛应用于以下几个领域: (1) 企业品牌管理与危机预警:系统能够自动发出警报,为企业的公关部门提供应对策略和决策依据,帮助企业迅速做出反应,避免危机的进一步扩展。 (2) 政府舆情监管与社会治理:政府部门能够利用该系统的热点事件排名、舆情…

北汇信息致客户的一封感谢信

北汇信息致客户的一封感谢信尊敬的客户:感谢您选择北汇信息!2024年是不平凡的一年,中国汽车产量再创新高,出海与内卷挑战不断。北汇信息作为汽车电子测试领域的服务商,秉承“价值创造、共享成功”的理念,一直致力于为国内外汽车客户提供优质的产品和服务,共同面对这些挑…

001 修改博客园侧边栏的顺序

打开配置页:https://i.cnblogs.com/settings在“博客侧边栏公告”添加代码<script> $(document).ready(function(){//returnvar list=[sidebar_recentcomments,//最新评论sidebar_categories,//随笔分类、随笔档案sidebar_toptags,//我的标签sidebar_shortcut,//常用链接…

销售进阶:三步提问法,掌握客户心理

在销售行业,时间就是金钱,我们必须争分夺秒地搞定客户。但也不能盲目行动,而要稳扎稳打。关键在于快速抓住客户需求,而客户往往不会主动透露他们的需求,甚至自己都不清楚自己想要什么。这就需要我们通过巧妙的提问来破局,否则忙活半天也只是白费力气。 最让人头疼的是,跟…

寒假集训笔记 | | 第一课

C++STL --第一课 C标准库常用函数<cstring>memset() 暴力清空 char str[10]; memset(str,0,sizeof(str));<cmath>三角函数、指数函数、浮点取整函数<cstdlib>qsort() C语言快排 rand() 随机数 malloc() free() C语言动态内存分配<cctype>isdigit()…

Svelte 最新中文文档翻译(1)—— 概述与入门指南

前言 Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构…

平面二连杆机构的动力学方程

动力学研究物体的运动和作用力之间的关系。机器人动力学问题有两类:一是已知机器人各关节的驱动力或力矩,求解机器人各关节的位置、速度和加速度,这是动力学正问题;二是已知各关节的位置、速度和加速度,求各关节所需的驱动力或力矩,这是动力学逆问题。机器人的动力学正问…

【红队】C2框架:Covenant

一、项目介绍 Covenant是一个.NET开发的C2(command and control)框架,旨在突出.NET的攻击面,并充当红队成员的协作命令和控制平台,该工具不仅支持Linux,MacOS和Windows,还支持docker容器,最特别的地方是支持动态编译,能够将输入的C#代码上传至C2 Server,获得编译后的文…

3. 使用sql查询csv/json文件内容,还能关联查询?

1. 简介 我们在前面的文章提到了calcite可以支持文件系统的数据源适配, 其实官方已经提供了相应的能力, 其支持csv和json的查询适配, 废话不多说, 直接展示. 2. Maven <!-- calcite文件系统支持 --> <dependency><groupId>org.apache.calcite</groupId>…

一文搞懂 APP 算法备案

今天来给大家好好科普一下超重要的 APP 算法备案,这可是和我们日常使用 APP 以及 APP 运营都息息相关的知识点哦! 什么是算法备案 简单来讲,算法备案就相当于 APP 运营者要把自家 APP 里使用的算法详情,向有关部门进行申报登记。这就如同给算法这个 “幕后大脑” 办一张正式…

IDEA 在远程 Tomcat 上运行项目(转载补充版)

转载:IDEA 在远程 Tomcat 上运行项目(亲身避坑版) 我在操作的时候,遇到个问题,提示Unable to open debugger port (192.168.252.232:54578): java. net. ConnectException "Connection refused: connect" 原因是,开启JVM调试,需要在2.1小节设置环境变量的时候…