当前位置: 首页 > news >正文

深入理解 Git 分支操作的底层原理

在软件开发的世界里,Git 已经成为了版本控制的标配工具。而 Git 分支功能,更是极大地提升了团队协作和项目开发的效率。我们在日常开发中频繁地创建、切换和合并分支,但是这些操作背后的底层原理是怎样的呢?在之前的博客探秘Git底层原理中介绍了git最基础命令的底层原理,接下来,我们继续深入学习Git 分支操作的底层原理

一、Git 分支的本质:轻量级指针

在 Git 中,分支实际上就是一个轻量级的指针,它指向一个特定的 Commit 对象。默认情况下,Git 仓库会有一个名为 master(现在很多仓库默认是 main)的分支,它指向项目的初始提交

1.1 分支的创建

当我们使用 git branch <branch-name> 命令创建一个新分支时,Git 只是简单地在 .git/refs/heads 目录下创建了一个新的文件,文件名为分支名,文件内容就是当前分支所指向的 Commit 对象的哈希值。由此看在git中新建分支的开销是十分小的,它只是创建了一个指向commit的指针,但是效果却是十分重要的,我们可以在不影响之前分支的前提下对现有代码做修改。(集中式版本控制系统svn每次创建分支会将之前的代码重新复制一遍,开销很大) 例如,执行 git branch feature 命令后,.git/refs/heads 目录下会出现一个名为 feature 的文件,其内容和 master 分支指向的 Commit 哈希值相同。这意味着 feature 分支和 master 分支在创建时指向同一个 Commit 对象。

1.2 分支的切换

使用 git checkout <branch-name>git switch <branch-name> 命令可以切换分支。当我们切换分支时,Git 会更新 HEAD 指针,使其指向新分支的引用文件。HEAD 指针是一个特殊的引用,它始终指向当前所在的分支。例如,当我们从 master 分支切换到 feature 分支时,HEAD 指针会从 .git/refs/heads/master 指向 .git/refs/heads/feature。此时,工作目录的内容会更新为新分支所指向的 Commit 对象对应的项目状态。

1.3 分支的移动

当我们在某个分支上进行新的提交时,该分支的指针会自动向前移动,指向新的 Commit 对象。例如,在 feature 分支上进行了一次提交,feature 分支对应的引用文件(.git/refs/heads/feature)中的哈希值会更新为新 Commit 对象的哈希值,而 master 分支的指针不会受到影响。这就是 Git 能够支持并行开发的关键,不同的分支可以独立发展,互不干扰。

二.分支引用

了解了分支的原理后我们可以打开git仓库找到分支的引用,相关目录在.git/refs/heads中。这部分我们通过实操了解git分支的机制

我们先初始化一个仓库,init之后.git/refs/heads文件夹中为空。

这里我们先在一个初始化过的仓库新建并编辑一个文件1.txt,然后进行第一次提交,这时查看文件夹中内容,此时有一个对应的master文件,用记事本打开文件内容
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

里面是如图的哈希值,对照git中的提交值,这正是第一次commit后的对象id,说明分支中保存的就是指向的commit的id

下面我们再重建一个分支,此时文件夹中也对应生成了该分支引用。
在这里插入图片描述
在这里插入图片描述

后面我们添加1.txt内容并保存,再切回master分支并进行合并,可以看到,合并后两个分支都指向最新的提交,内容也都存的最新提交的哈希值

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

二、分支的合并:快进模式和冲突处理

在开发过程中,我们经常需要将一个分支的修改合并到另一个分支中。Git 提供了两种主要的合并方式:快进合并和三方合并。

2.1 快进合并

当一个分支是另一个分支的直接下游,即没有分叉时,Git 会使用快进合并。例如,feature 分支是从 master 分支创建的,并且在 feature 分支上进行了一系列提交,而 master 分支没有任何新的提交。此时,当我们将 feature 分支合并到 master 分支时,Git 只需要将 master 分支的指针直接移动到 feature 分支所指向的 Commit 对象即可。这种合并方式非常简单和高效,不会产生新的 Commit 对象。

2.2 三方合并(冲突处理)

当两个分支有不同的提交历史,即发生了分叉时,Git 会使用三方合并。三方合并需要找到两个分支的共同祖先 Commit 对象(合并基础),以及两个分支各自的最新 Commit 对象。Git 会将这三个 Commit 对象对应的 Tree 对象进行比较和合并,生成一个新的 Commit 对象,该 Commit 对象有两个父 Commit 对象,分别指向合并前的两个分支的最新 Commit 对象。这个新的 Commit 对象代表了合并后的项目状态。

三、删除分支:清理不再需要的引用

当一个分支的开发任务完成并且已经合并到主分支后,我们可以使用 git branch -d <branch-name> 命令删除该分支。删除分支实际上就是删除 .git/refs/heads 目录下对应的引用文件。需要注意的是,如果分支上有未合并的提交,使用 -d 选项删除分支会失败,此时可以使用 -D 选项强制删除。

四、总结

Git 分支操作的底层原理基于其强大的对象存储和引用管理机制。通过轻量级的分支指针,Git 能够高效地支持并行开发,让团队成员可以在不同的分支上独立工作。而合并操作则允许我们将不同分支的修改整合到一起,确保项目的顺利推进。深入理解 Git 分支操作的底层原理,不仅可以帮助我们更好地使用 Git 进行版本控制,还能在遇到复杂的分支问题时,快速定位和解决问题。

相关文章:

  • SZU 编译原理
  • 深度学习笔记23-LSTM实现火灾预测(Tensorflow)
  • C++_STL_map与set
  • HNUST湖南科技大学-安卓Android期中复习
  • 【Android构建系统】了解Soong构建系统
  • 算法基础 -- 小根堆构建的两种方式:上浮法与下沉法
  • 一款强大的压测带宽工具-iperf3
  • 容器编排利器-k8s入门指南
  • [AI算法] LLM训练-构建transformers custom model
  • 容器化-k8s-使用和部署
  • 前端面经 手写Promise
  • Linux 内核中 inet_accept 的实现与自定义传输协议优化
  • 部署docker上的redis,idea一直显示Failed to connect to any host resolved for DNS name
  • Tcping详细使用教程
  • .NET Core liunx二进制文件安装
  • 能源数字化转型关键引擎:Profinet转Modbus TCP网关驱动设备协同升级
  • 《k-means 散点图可视化》实验报告
  • 简单入门RabbitMQ
  • OrangePi Zero 3学习笔记(Android篇)11 - IR遥控器
  • python自学笔记2 数据类型
  • 东部沿海大省浙江,为何盯上内河航运?
  • 铁路端午假期运输火车票今日开售,12306提升应对超大规模并发访问需求能力
  • 梅花奖在上海|舞剧《朱鹮》,剧里剧外都是生命的赞歌
  • 巴基斯坦与印度停火延长至18日
  • 习近平向多哥新任领导人致贺电
  • 商务部:中方敦促美方尽快停止232关税措施