baixiaoji / blog

writting & thinking
3 stars 0 forks source link

高阶 Git 101 - 概念篇 #45

Open baixiaoji opened 5 months ago

baixiaoji commented 5 months ago

文档目标: 帮助读者了解有哪些 GIT 概念 / Git 对象以及对象如何分辨

作为工程师日常工具 Git ,通常用来进行版本控制使用。即便日常使用 IDE 编码,每人都高频使用 Git。 日常使用 Git 20% 能力就可以 cover 80% 使用场景,另外 80% Git 能力也可以协助我们提升日常使用效率。

申明后续笔者使用 git 版本 2.44, 后续部分涉及功能存在版本限制。读者在阅读过程中可以自行升级 git 版本

brew install git@2.44.0

命令模型

git 命令模型主要分为上下两层:高阶命令(porcelain)和低阶命令(plumbing)。日常使用高阶命令为主,每一个高阶命令会由多个低阶命令组合组合而成,从而完成任务,而低阶命令更像 utils 函数一个命令只做一件事。

在命令行通过 man git 方式进行预览 git 文档,上下翻页即可查看命令细则。

作为国人,对 git 低高阶命令命名方式不是很理解,为什么命名和瓷器和管道有关呢?查完资料发现和水管工作有关🫣:

在一个房子中,"plumbing"(管道)是隐藏在墙壁和地板下的基础设施,它负责将水和其他流体从一个地方传输到另一个地方。这些管道通常是由专业的水管工人安装和维护的,普通的房屋使用者很少直接接触到它们。

相比之下,"porcelain"(瓷器)是指那些用户直接接触到的设备,例如水龙头、淋浴头、马桶等。这些设备通常有更好的用户界面,更容易使用,但它们的工作原理和内部结构对用户来说是隐藏的。

plumbing 命令就像水管,它们是 Git 的基础设施,负责完成一些基础原子级别任务;porcelain 命令就像是瓷器,它们提供了一个更好的用户界面,更容易使用。这些命令封装了 plumbing 命令的复杂性,提供了一些更高级的、更易于理解的功能。

Git 对象

了解完命令过后,说到最核心 git 对象,git 内部所有对象和之前关系如下图。

其中核心对象类型有三类:

这三类对象均存在 .git/objects 目录下,上述所有节点在 git 中真正含义是 sha1 值。简单来说这些对象都以值的形式存在下来,而对应的哈希值( sha1 值)就是存储在目录+文件名(前两位是目录名称,后续为文件名)。

哈希值类似网络当中的ip地址一样存在记忆难度,边派生出了 branch 和 tag 通俗命名方式进行指向目标哈希值。

日常工作流讲解:

在日常操作中先 git add 然后完成 git commit,前者是将工作区文件内容转化为 blob 对象和生成哈希值(sha1 A),并将blob 对象内容存在在暂存区,后者是创建 tree 对象和哈希值(sha1 B)进行收敛这部分暂存区内容(文件名称 + sha1 A),同时结合 git config 信息和提交信息生成 commit 对象和哈希值指向(sha1 B)进行关联,将暂存区内容存储到本地仓库。

如何快速查看暂存区存储哪些对象?

git ls-files --stage 

image

命令输出当前仓库中被跟踪的对象,第二段信息是各文件 sha1 哈希值。

如何对象是哪种类型?

git cat-file -t <sha1-hash>

image

如何快速查看对象内容是什么?

git cat-file -p <sha1-hash>

image 如果当前 git 版本较高或者经常有手动运行 git gc等命令,.git/objects目录下并不会有哈希值文件。

上述三类对象在存储初期是单独文件进行存储,这些对象称为 loose objects,而 git 会定期将多个 loose objects打包为一个文件,这些文件被称为 packfile。

在 packfile 中,对象被压缩,并且相似的对象被有效地去重,以减少存储空间的使用。这种打包的对象称为 "packed objects"。这部分文件存储在.git/objects/pack文件当中,可以使用下述命令进行查看

git verify-pack -v <packfile-name>

这个命令会列出 packfile 中的所有对象,包括它们的类型、大小、偏移量等信息。git verify-pack 命令的输出可能会非常长,特别是对于包含大量对象的大型仓库。你可能需要使用 less 或 grep 等工具来查看或搜索这个输出。