Git内部构造速读

举报
唐里 发表于 2021/07/15 10:52:29 2021/07/15
【摘要】 用 DAG 快速介绍一下 Git 的内部构造。

快速介绍一下 Git 的内部构造给那些不怕DAG(有向无环图)这类词汇的人们。20210624-152456(WeLinkPC).gif

储存

简单来说,git对象存储就是不同类型的DAG对象。它们都被压缩存储并以一个SHA-1哈希值标识(顺便说一句,这并不是它们所代表的文件内容的SHA-1,而是它们在git中的标识)。

blob

blob:最简单的对象,只是一堆字节;通常是一个文件,但也可以是一个符号链接或几乎其他任何东西;blob 的的语义由指向它的对象决定。

tree

tree:目录由tree对象表示。tree 内容包括:指向表示文件内容的 blob、表示子目录的其它 tree,以及文件名、访问模式信息等。

当一个节点指向DAG的另一个节点时,它们产生依赖——没有另一个节点它就不能存在。没有任何指向的节点可以使用git gc进行垃圾回收;没有文件名指向的文件系统inode可以通过git fsck -- lost-found修复。

commit

commit:一个commit指向一个代表提交时的文件状态的tree。 它还指的是作为其父项的 0~n 个其他commit。 多个父项意味着这是合并的commit,没有父项意味着它是初始提交,有趣的是可以有多个初始提交 —— 这通常意味着合并了两个独立的项目。 commit对象的主体是commit message(提交说明)。

refs

refs:Git 内部表示分支和标签的机制。由于DAG中的新节点只能关联到现有节点,不能改变现有节点,因此refs就像就像贴在DAG节点上的便利贴可以自由移动。 它们不会存储在历史记录中,也不会在存储库之间直接传输。它们相当于书签:“我当前在这里”。

git commit在DAG中添加一个节点,并将当前分支的便签移动到这个新节点。

HEAD ref是特殊的,因为它实际上指向另一个ref,它是指向当前活跃分支的指针。普通ref是在命名空间heads/XXX中,但是通常可以跳过head/部分。

remote refs

remote refs:与普通refs的不同之处在于命名空间的不同,并且remote refs实际上是由远程服务器. git fetch来控制更新的。

tag

tag:tag指向commit,包括 optional messageGPG signature。tag既是DAG中的一个节点,又是一个标签标签只是访问标记的一种快速方式,如果丢失了,可以使用git fsck --lost-found从DAG中恢复。

DAG 中的节点可以从存储库移动到存储库,以更有效的形式(packs)存储,未使用的节点会被当做垃圾收集。但是最终,git 存储库永远只是DAG和post-its。


历史记录

至此,我们已经掌握了git如何存储版本历史的知识,接下来看看如何可视化合并之类的东西,以及git与那些试图将历史管理为每个分支的线性变化的工具有何不同。

clone

上图是最简单的存储库,我们已经克隆了一个包含一个commit的远程存储库。

fetch

在这里,我们通过 git fetch 从远程获取一个新的commit,但是还没有合并它。

merge

进行git merge remotes/MYSERVER/master 后,由于合并是快进 fast forward 操作,在本地分支上没有新的 commit,本次只是将 “便签纸” 进行了移动,并修改了当前工作目录下的相关文件。

commit

本地进行 git commit 和 git fetch 之后,我们得到一个新的本地commit和一个新的远程commit。显然,合并是必要的。

merge again

上图是Git merge remotes/MYSERVER/master 的结果。由于这次不是 fast forward,因此会在 DAG 中创建一个新节点,该节点有两个父 commit 节点。

more commits

上图是进行多次 commit 和 merge 操作后可能的样子。可以看到出现了 “缝线” 模式。git 的 DAG 准确地记录了操作的历史。

stitching

当还没有对你的分支进行发布时,可以对你的分支进行 git rebase 操作,即你的 commit 被另一个具有不同父 commit 的 commit 替换。旧 commit 会一直保留在 DAG 中直到被垃圾回收。如果有额外的 post-its 指向旧commit,它们将继续指向它,并使旧commit无限期地存活下去。

使用 git gc 进行垃圾回收,然后创建一个新的 commit 后:

garbage collect

rebase也可以对多个commit进行rebase操作:

rebase

原文链接:https://eagain.net/articles/git-for-computer-scientists/

【版权声明】本文为华为云社区用户翻译文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容, 举报邮箱:cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。