【git】git分支之谜-十分钟给你讲透彻

这里写自定义目录标题

  • 引子
  • 分支的直观模型
  • 在 git 中,分支是完整的提交记录
  • 分支用commit ID存储
  • 人们的直觉通常并没有那么错
  • rebase 使用“直观”的分支概念
  • `merge`也使用“直观”的分支概念
  • github pull request 也使用直观的想法
  • 直觉很好,但它也有一些局限性
  • 主干和分支
  • git 允许你“向后”进行 rebase
  • git 的分支之间缺乏层次结构,这有点奇怪
  • git 的分支 UI 也很奇怪
  • 在 GitHub 中,default分支是特殊的
  • 就这样!

引子

关于git branch,我经常听到人们说他们觉得 git branch的工作方式违反直觉。 我就纳闷了:什么是“直觉”的分支概念,它与 git 的实际工作方式有何不同?

因此,在这篇文章中,我想简单谈谈

1)我认为很多人都有直观的思维模型
2)git 内部如何表示分支(“分支是指向提交的指针”等)
3)“直观模型”和其实际运作方式实际上是非常密切相关的
4)直观模型的一些局限性以及它可能导致问题的原因

这篇文章中没有一些很新颖的东西,都是些常识性的东西。

分支的直观模型

当然,人们对branch有许多不同的直觉。我认为以下直觉与现实的“苹果树的分支”比喻最为接近的。

我猜很多人会这样看待 git 分支:下图中粉红色的有两次提交的是一个“分支”。

在这里插入图片描述
我认为该图有两个重要之处:

1)该分支上有 2 个提交
2)该分支有一个“父级”(main),它是其的一个分支

这似乎很有道理,但 git 定义分支的方式并不是这样——最重要的是,git 没有分支“父级”的概念。那么 git 如何定义分支呢?

在 git 中,分支是完整的提交记录

在 git 中,分支是所有先前提交的完整历史记录,而不仅仅是“分支”提交。因此,在上面的图片中,两个分支(main和branch)都有 4 个提交。

git上有一个示例存储库,其分支设置方式与上图相同。让我们看看这两个分支:

main有 4 条提交:

$ git log --oneline main
70f727a d
f654888 c
3997a46 b
a74606f a

并且mybranch也有 4 个提交。底部的两个提交在是两个分支共同的。

$ git log --oneline mybranch
13cb960 y
9554dab x
3997a46 b
a74606f a

因此mybranch,它有 4 个提交,而不仅仅是 2 个提交13cb960,而且9554dab这些提交都是“分支”提交。

你可以让 git 用下面的命令显示所有的提交:

$ git log --all --oneline --graph
* 70f727a (HEAD -> main, origin/main) d
* f654888 c
| * 13cb960 (origin/mybranch, mybranch) y
| * 9554dab x
|/
* 3997a46 b
* a74606f a

分支用commit ID存储

在 git 内部,分支被存储为带有提交 ID 的小型文本文件。该提交是分支上的最新提交。这就是我在开头提到的“技术上正确”的定义。

让我们看一下示例 repo 中的main文本文件:mybranch

$ cat .git/refs/heads/main
70f727acbe9ea3e3ed3092605721d2eda8ebb3f4
$ cat .git/refs/heads/mybranch
13cb960ad86c78bfa2a85de21cd54818105692bc

这是有道理的:70f727是main分支上的最新提交,并且13cb96是mybranch上的最新提交。

这种方法之所以有效,是因为每个提交都包含一个指向其父级的指针,所以 git 可以按照指针链来获取分支上的每个提交。

就像我之前提到的,这里缺少的是这两个分支之间的关系。没有迹象表明这mybranchmain的一个分支。

我们已看到了分支的直观概念是如何“错误的”,但是它在一些非常重要的方面又是正确的。

人们的直觉通常并没有那么错

我认为告诉人们他们对 git 的直觉是“错误的”这种说法相当正常。我觉得这有点愚蠢——一般来说,即使人们对某个东西的看法在技术上是错误的,但是他们通常也会出于非常正当的理由而产生这种直觉!“错误”的模型可能非常有用。

因此,让我们从 3 个方面来讨论一下分支的直观“分支”概念与我们在实践中实际使用 git 的方式非常接近。

rebase 使用“直观”的分支概念

来再看看篇头的那个图
在这里插入图片描述

当你在main 分支对分支mybranch上进行rebase时,它会将“直观”分支上的提交(仅 2 个粉红色提交)重放到 上main。

结果是只有 2 (x和y) 被复制。如下所示:

$ git switch mybranch
$ git rebase main
$ git log --oneline mybranch
952fa64 (HEAD -> mybranch) y
7d50681 x
70f727a (origin/main, main) d
f654888 c
3997a46 b
a74606f a

这里git rebase创建了两个新的提交(952fa64和7d50681),其信息来自前两个x和y提交。

所以直观模型并没有错!它准确地告诉你在 rebase 中发生了什么。

但是因为 git 不知道mybranchmain的一个分支,所以你需要明确告诉它在哪里重新定位分支。

merge也使用“直观”的分支概念

合并不会复制提交,但它们确实需要一个“基本”提交:合并的工作方式是查看两组更改(从共享基础开始),然后合并它们。

让我们撤消刚刚执行的变基,然后看看合并基础是什么。

$ git switch mybranch
$ git reset --hard 13cb960  # undo the rebase
$ git merge-base main mybranch
3997a466c50d2618f10d435d36ef12d5c6f62f57

这给了我们分支所在的“base”提交3997a4。根据我们的直观图片,你可能会认为这就是提交。

github pull request 也使用直观的想法

如果我们在 GitHub 上创建一个合并merge mybranchmain,它还会向我们显示 2 个提交:提交x和y。这很有意义并且也符合我们对分支的直观概念。

在这里插入图片描述
我假设如果你在 GitLab 上发出合并请求,它会显示类似的内容。

直觉很好,但它也有一些局限性

实际上让我们对分支的直观定义感觉上是不错的!分支的“直观”概念与merge、rebase 以及 GitHub pull 请求的工作方式完全匹配。

在merge、rebase或者 pull 请求时(例如git rebase main),你确实需要明确指定其他分支,因为 git 不知道你想基于哪个分支。

但是分支的直观概念有一个相当严重的问题:你直观地思考的方式在main分支和其他分支的方式不同, 但是git 并不知道这一点。

那么让我们来探讨一下不同类型的 git 分支。

主干和分支

对于人类来说,mainmybranch是相当不同的,并且你在如何使用它们方面可能有着相当不同的意图。

我认为将一些分支视为“主干”分支,将一些分支视为“分支”是很正常的。你也可以拥有分支的分支。

当然,git 本身并没有做出这样的区分(“分支”这个术语是我编造的!),但它是哪种分支肯定会影响你如何区分对待它。

例如:

1)你可能会重新rebase了 mybranch 到 main 但你可能不会把main分支rebase到mybranch,那就很奇怪了!
2)一般而言,人们在在覆盖“主干”分支的历史记录时比在一些短期的分支上覆盖历史记录时要谨慎得多

git 允许你“向后”进行 rebase

我认为 git 让人们感到困惑的一件事是 —— 因为 git 不知道一个分支是否是另一个分支的“分支”,所以它不会给你任何关于是否/何时适合将分支 X 重新定位到分支 Y 上的指导,你只需要知道。

例如,您可以执行以下任一操作:

$ git checkout main
$ git rebase mybranch

或者

$ git checkout mybranch
$ git rebase main

Git 很乐意让你做任何一种,尽管在这种情况下git rebase main非常正常而且git rebase mybranch很奇怪。很多人说他们觉得这很令人困惑,这里有一张两种 rebase 的图片:

在这里插入图片描述

类似地,你可以“向后”进行merge,尽管这比执行向后rebase更为常见 - 出于不同的原因,merge mybranchmain和main merge到 mybranch都是有用的事情。

以下是两种合并方式的图表:在这里插入图片描述

git 的分支之间缺乏层次结构,这有点奇怪

我经常听到“main分支并不特殊”的说法,对此我感到很困惑——在我工作的大多数存储库中,main分支都 非常特殊!为什么人们说它不特殊?

我认为关键在于尽管分支之间确实和main存在关系(通常很特殊!),但 git 对这些关系并不感知。

每次运行 git 命令(例如git rebasegit merge)时,都必须明确告诉 git 分支之间的关系,如果您犯了错误,事情就会变得非常奇怪。

我不知道 git 在这里的设计是“正确”还是“错误”(它肯定有一些优点和缺点,而且我已经厌倦了阅读关于它的无休止的争论),但我确实认为它让很多人感到惊讶,这是有原因的。

git 的分支 UI 也很奇怪

假设您只想查看分支上的“分支”提交,正如我们所讨论的,这是完全正常的事情。

下面演示了如何使用以下命令查看我们分支上的 2 个分支提交git log:

$ git switch mybranch
$ git log main..mybranch --oneline
13cb960 (HEAD -> mybranch, origin/mybranch) y
9554dab x

你可以像这样查看这 2 次提交的合并差异git diff:

$ git diff main...mybranch

因此,用git log查看带有的2 个提交(x和y),需要使用 2 个点 (… ) git log .. ,但要用git diff查看带有的相同提交,您需要使用 3 个点 (… ) , 如 git diff...

就我个人而言,我永远无法记住…和…是什么意思,所以我完全避免使用它们,尽管原则上它们看起来很有用。

在 GitHub 中,default分支是特殊的

另外,值得一提的是,GitHub 确实有一个“特殊分支”:每个 GitHub repo 都有一个“默认分支”(用 git 术语来说,它就是HEAD指向的),它在以下方面是特别的:

1) 这是你在git clone存储库中签出的内容
2) 这是拉取请求的默认目的地
3)github 会建议你保护默认分支不被强制推送

或许还有更多我没有想到的。

就这样!

回想起来,这一切似乎都非常明显,但我花了很长时间才弄清楚分支的更“直观”的想法是什么,因为我已经习惯了技术上的“分支是对提交的引用”的定义。

我也没有真正想过 git 如何让你在每次运行git rebase 或者 git merge 时告诉它分支之间的层次结构——对我来说,这样做是第二天性,没有什么大不了的,但现在我想想,很容易看出为什么有人会混淆。

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

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

相关文章

前端编程艺术(1)---HTML

目录 1.HTML 2.注释 3.标题标签 4.段落标签 5.换行与水平分隔线 6.文本格式化标签 7.图像标签和属性 8.超链接 8.列表标签 9.表格标签 10.表单标签 11.HTML5 1.HTML HTML(HyperText Markup Language,超文本标记语言)是一种用于创建…

【JAVA开源】基于Vue和SpringBoot的新闻推荐系统

本文项目编号 T 056 ,文末自助获取源码 \color{red}{T056,文末自助获取源码} T056,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

Node-RED系列教程-23node-red获取OPCDAServer数据(DCOM配置)

准备了一个干净的windows 2016虚拟机: administrator wong@123 以管理员身份进入系统: 准备好如下软件: 使用的nodejs版本为: 设置淘宝镜像源: npm config set registry https://registry.npmmirror.com 安装nodered: npm install -g --unsafe-perm node-red@2.2.2

如何组织鼠标的默认的事件

如何组织鼠标的默认的事件 我原先的代码是 dblclick"checkNode(data)"设置了一个双击的事件,我如果双击的话就会导致这个内容被选中。 选中内容的同时会触发浏览器默认的操作,导致出现复制的框这些东西。 解决的方法。加一句。 mousedown.pr…

Power apps:一次提交多项申请

1、添加一个Form,导入sharepoint列表,添加确认,继续,取消按钮 2、在页面的onvisible属性中添加 Set(applynumber,Last(付款申请表).申请编号1); #定义一个申请编号变量,每次申请,就将列表最后一个…

2024上海网站建设公司哪家比较好TOP3

判断一家网建公司的好坏,第一是看公司背景,包括成立时间,工商注册信息等,第二可以去看看建站公司做的案例,例如,网站开发、设计、引流等等的以往案例,了解清楚具体的业务流程。 一、公司背景 …

让小脚本成为自己高效测试的工具

测试中会遇到的工具 软件测试如果仅仅靠手工去执行会发现在很多地方力不从心,虽然市面上已经有大牛开源了一些测试工具可以供我们使用但是在一些公司特有的业务方面则需要我们借助开源或重新做一个自己的测试工具。 测试常用的开源工具 死链接检测工具 Xenu home…

【羊毛资源】华为云开发者云主机免费申请使用指南

本文内容均来自个人笔记并重新梳理,如有错误欢迎指正! 如果对您有帮助,烦请点赞、关注、转发、订阅专栏! 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】(全…

SpringAOP实现的两种方式-JDK动态代理和CGLIB动态代理

前言 想要了解SpringAOP的实现方式,需要先了解什么是AOP OOP和AOP的区别 OOP 面向对象,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。 AOP,一般称为…

解决Cloudflare 521错误的四种方法

在使用Cloudflare进行网站加速时,错误521是一个常见的问题,表示“Web服务器关闭”。当你访问某个使用Cloudflare的网站时,如果原始服务器拒绝了Cloudflare的连接请求,浏览器就会显示此错误信息。本文将详细介绍导致错误521的原因&…

如何将list嵌套的list的[]去掉

如果list里里面的元素是数字,‘1’也是可以的,那么我们可以使用np.ravel a [[1,2,3], [5, 2, 8], [7,8,9]]list(np.ravel(a)) #[1, 2, 3, 5, 2, 8, 7, 8, 9]对于不规则List c[[‘云阳站’], [‘双江’, ‘木古’], [‘滨双线’], [‘滨双线’, ‘云田线…

CRM在客户生命周期管理中的高效应用

企业要想在市场中持续增长并脱颖而出,就必须深刻理解并有效管理客户生命周期。客户生命周期,简而言之,是指从客户首次接触企业到最终与企业关系终止的全过程,它涵盖了多个关键阶段,每个阶段都蕴含着不同的机遇与挑战。…

无线领夹麦克风哪个牌子好?2024年口碑最好的领夹麦克风品牌推荐

举国同庆的国庆节快要到了,相信不少朋友都想趁此机会多拍摄一些Vlog来记录美好节日,想要音质效果好,领夹麦克风少不了!但是无线领夹麦克风行业看似繁荣的背后,却隐藏着一些不为人知的黑幕。从夸大信号稳定性到忽视音质…

0代码、自动化,让AI视觉算法赋能千行百业(含源代码)

AI视频卫士通过自动化机器学习技术,降低AI开发和训练的门槛,让更多行业能够轻松接入AI,解决实际问题。 例如一个不懂AI的产品经理,但是他知道他想要能够检测到垃圾桶是否装满溢出,那么他只需要上传垃圾桶装垃圾溢的场景…

LangChain进阶技巧:提高聊天机器人性能的策略[第三课]

LangChain应运而生,为开发者们提供了一种高效、便捷的工具,助力他们构建出功能强大的大型语言模型应用。本文将带您走进LangChain的世界,揭秘其背后的技术原理,探讨如何利用这一利器来拓展语言模型的无限可能。通过丰富的实例分析…

“DNA亲和纯化测序:汇智生物的精准分析“

🌱 汇智生物 | 专注农业&植物基因组分析 🌱 🎓 教授【优青】团队亲自指导!提供专业实验设计、数据分析、SCI论文辅助等全方位服务。精准高效,为农植物科研保驾护航! 🔬 专业实验外包服务&am…

正点原子阿波罗STM32F429IGT6移植zephyr rtos(二)---使用I2C驱动MPU6050

硬件平台:正点原子阿波罗STM32F429IGT6 zephyr版本:Zephyr version 3.7.99 开发环境:ubuntu 24.4 zephyr驱动开发与之前接触到的开发方式可能都不一样,更像是linux驱动开发,zephyr源码里边其实已经有写好的I2C和MPU60…

ST-GCN模型实现花样滑冰动作分类

加入深度实战社区:www.zzgcz.com,免费学习所有深度学习实战项目。 1. 项目简介 本项目实现了A042-ST-GCN模型,用于对花样滑冰动作进行分类。花样滑冰作为一项融合了舞蹈与竞技的运动,其复杂的动作结构和多变的运动轨迹使得动作识别成为一个具…

CRM如何实现对客户信息的全局管理?

在知识产权与科技服务领域中,企业如何精准把握客户需求,高效管理知识产权资产,成为了决定其竞争力的关键因素。传统的CRM虽在一定程度上提升了客户管理效率,但在面对知识产权这一复杂且多变的领域时,往往显得力不从心。…

Html jquery下拉select美化插件——selectFilter.js

1. Html jquery下拉select美化插件——selectFilter.js jQuery是一个广泛使用的JavaScript库,它简化了DOM操作、事件处理、动画以及Ajax交互,使得开发者能更高效地构建交互式网页。在本案例中,jquery.selectlist.js插件正是基于jQuery构建的&…