git原理学习记录:从基本指令到背后原理,实现一个简单的git

本文记录了学习git原理的过程,通过实现简单的git命令,理解了git的核心思想——对象数据库。从`init`开始,逐步介绍了`object`、`tree object`、`commit object`、`references`,并实现了相应的功能,包括`hash-object`、`cat-file`、`update-index`、`ls-files`、`write-tree`、`commit-tree`、`log`等。最后讨论了`tag`、`merge`和`rebase`等高级功能的原理。通过实践,加深了对git版本控制系统的理解。
摘要由CSDN通过智能技术生成

好家伙~

一开始我还担心 git 的原理会不会很难懂,但在阅读了官方文档后我发现其实并不难懂,似乎可以动手实现一个简单的 git,于是就有了下面这篇学习记录。

本文的叙述思路参照了官方文档Book的原理介绍部分,在一些节点上探讨代码实现,官方文档链接

看完本文你能:1. 了解 git 的设计思想。2. 收获一点快乐?

编程语言选择了 go,因为刚学不太熟悉想多使用一下。

这是我的仓库地址,但如果你和我一样是初学,直接看代码可能不能快速上手,推荐顺着文章看。

迷你git实现–链接

如果文章看得吃力可以跟着官方文档的原理部分操作一次再回头看,可能更易懂?(●’◡’●)

1. init

在学习 git 原理之前,我们先忘掉平时用的 commit,branch,tag 这些炫酷的 git 指令,后面我们会摸清楚它们的本质的。

要知道,git 是 Linus 在写 Linux 的时候顺便写出来的,用于对 Linux 进行版本管理,所以,记录文件项目在不同版本的变更信息是 git 最核心的功能。

大牛们在设计软件的时候总是会做相应的抽象,想要理解他们的设计思路,我们就得在他们的抽象下进行思考。虽然说的有点玄乎,但是这些抽象最终都会落实到代码上的,所以不必担心,很好理解的。

首先,我们要奠定一个 ojbect 的概念,这是 git 最底层的抽象,你可以把 git 理解成一个 object 数据库。

废话不多说,跟着指令操作,你会对 git 有一个全新的认识。首先我们在任意目录下创建一个 git 仓库:

我的操作环境是 win10 + git bash

$ git init git-test
Initialized empty Git repository in C:/git-test/.git/

可以看到 git 为我们创建了一个空的 git 仓库,里面有一个.git目录,目录结构如下:

$ ls
config  description  HEAD  hooks/  info/  objects/  refs/

.git目录下我们先重点关注 .git/objects这个目录,我们一开始说 git 是一个 object 数据库,这个目录就是 git 存放 object 的地方。

进入.git/objects目录后我们能看到infopack两个目录,不过这和核心功能无关,我们只需要知道现在.git/objects目录下除了两个空目录其他啥都没有就行了。

到这里我们停停,先把这部分实现了吧,逻辑很简单,我们只需要编写一个入口函数,解析命令行的参数,在得到 init 指令后在指定目录下创建相应的目录与文件即可。

这里是我的实现:init

为了易读暂时没有对创建文件/目录进行错误处理。

我给它取了个土一点的名字,叫 jun,呃,其实管它叫啥都可以(⊙ˍ⊙)

2.object

接下来我们进入 git 仓库目录并添加一个文件:

$ echo "version1" > file.txt

然后我们把对这个文件的记录添加进 git 系统。要注意的是,我们暂不使用add指令添加,尽管我们平时很可能这么做,但这是一篇揭示原理的文章,这里我们要引入一条平时大家可能没有听到过的 git 指令git hash-object

$ git hash-object -w file.txt
5bdcfc19f119febc749eef9a9551bc335cb965e2

指令执行后返回了一个哈希值,实际上这条指令已经把对 file.txt 的内容以一个 object 的形式添加进 object 数据库中了,而这个哈希值就对应着这个 object。

为了验证 git 把这个 object 写入了数据库(以文件的形式保存下来),我们查看一下.git/objects目录:

$ find .git/objects/ -type f    #-type用于制定类型,f表示文件
.git/objects/5b/dcfc19f119febc749eef9a9551bc335cb965e2

发现多了一个文件夹5b,该文件夹下有一个名为dcfc19f119febc749eef9a9551bc335cb965e2的文件,也就是说 git 把该 object 哈希值的前2个字符作为目录名,后38个字符作为文件名,存放到了 object 数据库中。

关于 git hash-object 指令的官方介绍,这条指令用于计算一个 ojbect 的 ID 值。-w 是可选参数,表示把 object 写入到 object 数据库中;还有一个参数是 -t,用于指定 object 的类型,如果不指定类型,默认是 blob 类型。

现在你可能好奇 object 里面保存了什么信息,我们使用git cat-file指令去查看一下:

$ git cat-file -p 5bdc  # -p:查看 object 的内容,我们可以只给出哈希值的前缀
version1

$ git cat-file -t 5bdc  # -t:查看 object 的类型
blob

有了上面的铺垫之后,接下来我们就揭开 git 实现版本控制的秘密!

我们改变 file.txt 的内容,并重新写入 object 数据库中:

$ echo "version2" > file.txt
$ git hash-object -w file.txt
df7af2c382e49245443687973ceb711b2b74cb4a

控制台返回了一个新的哈希值,我们再查看一下 object 数据库:

$ find .git/objects -type f
.git/objects/5b/dcfc19f119febc749eef9a9551bc335cb965e2
.git/objects/df/7af2c382e49245443687973ceb711b2b74cb4a

(゚Д゚)发现多了一个 object!我们查看一下新 object 的内容:

$ git cat-file -p df7a
version2

$ git cat-file -t df7a
blob

看到这里,你可能对 git 是一个 object 数据库的概念有了进一步的认识:git 把文件每个版本的内容都保存到了一个 object 里面。

如果你想把 file.txt 恢复到第一个版本的状态,只需要这样做:

$ git cat-file -p 5bdc > file.txt

然后查看 file.txt 的内容:

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值