文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

三分钟上手!一文看懂 Git 的底层工作原理

2024-11-30 09:29

关注

Git 目录结构

Git 的本质是一个文件系统(很重要,记住这句话,理解这句话),工作目录中的所有文件的历史版本以及提交记录(commit)都是以文件对象的方式保存在 .git 目录中的。

我们先来创建一个名为 git-demo 空目录,并采用 git init 命令初始化 Git 仓库。该命令会在工作目录下生成一个 .git 目录,该目录将用于保存工作区中所有的文件历史的历史版本,commit,branch,tag 等所有信息。

$ mkdir git-demo
$ cd git-demo
$ git init

其目录结构如下:

图片

待会我们重点关注下这几个目录:

Git 三大对象

目前 Objects 目录中还没有任何内容,我们创建一个文件并提交:

$ git:(master) echo "my project" > README
$ git:(master) mkdir src
$ git:(master) echo "hello world" > src/file1.txt

添加并提交:

$ git:(master) git add .
$ git:(master) git commit -m "init commit"

图片

从打印输出可以看到,上面的命令创建了一个 commit 对象,该 commit 包含两个文件。查看 .git/objects 目录,可以看到该目录下增加了 5 个子目录 06,3b, 82, c5, ca,每个子目录下有一个以一长串字母数字命令的文件:

图片

这一大串是什么?

Git Object 目录中存储了三种对象:Commit, Tree 和 Blob,Git 会为对象生成一个文件,并根据文件信息生成一个 SHA-1 哈希值作为文件内容的校验和,创建以该校验和前两个字符为名称的子目录,并以 (校验和) 剩下 38 个字符为文件命名 ,将该文件保存至子目录下。

可以通过 git cat-file -t 哈希值 命令查看对象类型,通过 git cat-file -p 哈希值 命令查看对象中的内容,哈希值就是目录名+文件名,在没有歧义的情况下,命令可以不用输入整个哈希值,输入前几位即可。

我们挨个看下:

065bca(blob):

图片

3b18e(blob):

图片

824244(tree):

图片

c5bc98(commit):

图片

ca96(tree):

图片

认真看图,大家看完也就差不多清楚了 commit、blob、tree 这几大对象是什么东西了

从 commit 对象(c5bc98)入手,commit 对象中保存了 commit 的作者,commit 的描述信息,签名信息以及该 commit 中包含哪些 tree 对象和 blob 对象。从上图可知包含了 tree 对象(ca96)。

可以把 tree 对象看成这次提交相关的所有文件的根目录,可以看到 ca96 这个 tree 对象中包含了一个 blob 对象(065bca),即 README 文件,以及一个 tree 对象(824244),即 src 目录。而 blob 对象存储的就是真正的内容。

这几个对象的对应关系如下图所示:

图片

Git Brach 和 Tag

现在来看下 HEAD 中的内容,前面说过,HEAD 中存储的是工作目录当前状态对应的 commit:

$ git:(master) cat .git/HEAD
ref: refs/heads/master
$ git:(master) cat .git/refs/heads/master
c5bc98b8990bedd7444da537320559e601eba87b

c5bc98 正是我们最近的这次 commit!

master 是一个分支名,所以分支(branch)的本质是一个指向 commit 的指针

我们切一个新分支 feat/work:

图片

查看下 refs/heads/master 和 refs/heads/feat/work 中的 commit 值:

图片

从其内容可以看到,feat/work 这个 branch 并没有创建任何新的版本文件,和 master 一样指向了 c5bc98 这个 commit。

从上面的实验可以看出,一个 branch 其实只是一个 commit 对象的应用,Git 并不会为每个 branch 存储一份拷贝,因此在 git 中创建 branch 几乎没有任何代价。

接下来我们在 feat/work 这个 branch上进行一些修改,然后提交:

$ git:(feat/work) echo "new line" >> src/file1.txt
$ git:(feat/work) echo "do nothing" >> License
$ git:(feat/work) git add .
$ git:(feat/work) git commit -m "some change"

图片

查看当前的 HEAD:

图片

可以看到 HEAD 指向了 feat/work 这个 branch,而 feat/work branch则指向了 8a442 这个commit,master branch 指向的 commit 未变化,仍然是 c5bc98。

查看 8a442 这个commit对象的内容:

图片

可以看到 commit 有一个 parent 字段,指向了前一个 commit c5bc98。还包含了一个 tree 对象(2a9dd):

图片

可以观察到,由于 README 没有变化,还是指向的 065bca 这个blob对象。License 是一个新建的 blob 对象,src 和 file1.txt 则指向了新版本的对象。

增加了这次 commit 后,Git 中各个对象的关系如下图所示:

图片

Tag 和 branch 类似,也是指向某个 commit 的指针。不同的是 tag 创建后其指向的 commit 不能变化,而 branch 创建后,其指针会在提交新的 commit 后向前移动。

来源:飞天小牛肉内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯