软件构造 | Git原理

软件构造 这门课在实验中经常要用到Git指令,Git的指令也很简单,简单来讲常用的只有pull、commit、push,但是我们并不了解Git的很多原理以及细节,这篇blog会详细介绍这些东西。
本文中使用了git tree指令,在windows使用该指令可以参考文章:Git Bash下安装使用tree(在windows)

本文章主要参考视频https://www.bilibili.com/video/av77252063

Git如何存储信息

Git内部使用二进制的形式存储 ,如果使用cayt指令查看.git文件中的内容,看到的均是乱码。

新建.txt文件并且将其加入到暂存区中

git init
echo '111' > a.txt
echo '222' > b.txt
git add *.txt

使用tree .git/objects指令查看
在这里插入图片描述

使用cat指令查看内容,输出如下,因为git对数据进行了多次压缩,所以如果直接使用cat查看的话得到的数据均是乱码

xK▒▒OR0a044▒K▒

可以使用以下命令

git cat-file -t file_name		//输出文件类型
git cat-file -p file_name		//输出具体内容

在这里插入图片描述

上面中我们可以看到文件夹Objects和blob,Git Object为储存数据的最小单元,bolb object为储存文件的具体内容和。

在add的两个文件中,有一个文件的文件名为c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c,这是通过哈希算法得到的文件名,也就似乎一个Key值。Git内部实际上就是哈希表的结构,哈希值就是文件名,Value为blob。

接下来我们使用git commit指令,之后使用tree指令查看,可以看到多出来两个文件

在这里插入图片描述

以文件4caa为例,使用git cat-file指令查看多出来的文件的类型和内容

在这里插入图片描述

可以看到的多出来的文件的类型为tree,储存的内容是一个目录结构,从左往右依次为文件权限、文件类型、文件哈希值、文件名。使用commit指令之后Git对我们得到文件打了一次快照,储存在了tree object中。tree object中的哈希值可以帮助我们定位到本地库中的blob object。

对文件5a74同样使用git cat-file指令

在这里插入图片描述

其中存储的是作者、提交时间以及提交内容。

我们最后便可以得到如下的内容

在这里插入图片描述

分支信息存储在.git/HEAD中。可以用cat .git/HEAD指令查看目前的分支在哪个位置,之后使用cat指令查看分支内容,可以看到这是一个哈希值,他指向的就是我们刚刚的commit

在这里插入图片描述

HEAD、分支、普通的tag可以简单理解为一个指针,指向对应commit的哈希值,可以用下图表示

在这里插入图片描述

总结

在这里插入图片描述

Git object一旦创建之后就不可变更,但是最后一项可变更。

为何将文件权限和文件名存储在tree object而不是blob object?

如果将权限和文件名存储在blob object中,就算我们没有改变文件内容,只是修改了文件名,Git都会新建一个blob object文件,如果将这些信息存储在tree object,则只需要新建tree object即可。

Git的三个分区以及变更历史的形成

三个分区

  • 工作区
  • 暂存区
  • 仓库

刚刚的任务执行完之后,git三个分区的结构如下(索引也就是我们的暂存区)

在这里插入图片描述

使用git add可以将blob添加到暂存区,也就是创建blob文件,使用commit可以将文件提交到本地仓库,也就是创建tree node 和 commit。

如果我们修改a.txt中的内容(echo ‘333’ > a.txt),暂存区和仓库不会发生变化。之后使用git add a.txt,git仓库中会新建一个blob object,内容就是a.txt压缩之后的内容,之后将索引中原本指向a.txt的指针会指向新的a.txt

在这里插入图片描述

当我们执行commit指令之后,git的动作可以分为三步

  1. 新产生一个tree object,指向原来的b.txt和新的a.txt
  2. 产生一个新的commit,记录这次提交的信息,并且产生指向上一个commit的parent指针
  3. master的指针移动到新的commit

从以上三步我们不难发现,git每次commit之后,会生成一个全新的文件快照(tree object),而不是一个变更的部分,虽然耗费的空间比较多,但是时间复杂度低,以空间换时间。当文件很大的时候,git会自动压缩相似快照,无需我们手动操作

Git指令怎么保证历史记录不被篡改?

Git使用哈希表的结构,修改某一个节点上的文件,该节点的父节点以及不断往上的节点的哈希值都需要被修改,当其他人使用pull指令或者push指令的时候就会发现问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值