Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Git 对象存储结构分析

Git 对象存储结构分析

原创
作者头像
囚兔
修改于 2018-04-22 05:07:25
修改于 2018-04-22 05:07:25
3.2K2
举报
文章被收录于专栏:IT杂记IT杂记

1. 前言

Git 对象有:blob (数据块), tree (目录树), commit (提交), tag (标签)。

本文通过一个示例,以blob为例来讨论对象的存储结构。示例采用的git版本为2.17

2. 实践讨论

2.1. 生成Blob对象文件

首先创建一个测试git仓库

代码语言:txt
AI代码解释
复制
$ mkdir hello
$ cd hello
$ git init

然后通过创建一个文件 test,test的内容为 "hello", 可以看到test文件的字节长度为6, 是因为创建文件的时候自动在行末加上了换行符\n。对文件其执行 git add , 可以看到在.git/objects目录下面生成了一个子目录ce,ce目录下面有个文件013625030ba8dba906f756967f9e9ca394464a。

代码语言:txt
AI代码解释
复制
$ echo "hello" > test
$ du -b test
6       test
$ git add test
$ find .git/objects/ -type f
.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a

该文件即为git为 test 文件数据内容生成的blob对象文件,该对象的SHA值为ce013625030ba8dba906f756967f9e9ca394464a.

至此,产生两个问题:

  1. 对象文件的数据结构是什么样的 ?
  2. 对象的SHA值又是如何生成的 ?

2.2. 对象数据结构及SHA值

根据 Git-Internals-Git-Objects 文中的描述:

首先,对象文件数据结构如下图:

git-object-storage.png
git-object-storage.png
  • content: 表示数据内容
  • head: 对象头部信息
    • object type:对象类型,可选值为 blob, tree, commit
    • whitespace: 一个空格字符
    • content byte size:数据内容的字节数字符串
    • NUL:空字符,ASCII码值为0

然后, 对象的SHA值就是对上面这个数据结构执行SHA1 hash摘要算法得到的。

2.3. 动手验证

根据2.2中的规则来编码对2.1中的test文件内容生成一个SHA值,看是否和git生成的SHA值一致?

代码语言:txt
AI代码解释
复制
    // object content
    String content = "hello\n";
    byte[] contentBytes = content.getBytes();

    ByteBuffer buf = ByteBuffer.allocate(1024);


    buf.put("blob".getBytes()); // object type
    buf.put((byte) ' ');        // whitespace
    buf.put(Integer.toString(contentBytes.length).getBytes());  // content byte size numeric string
    buf.put((byte) 0);          // NUL
    buf.put(contentBytes);      // content

    buf.flip();

    // whole object bytes
    byte[] objectBytes = new byte[buf.remaining()];
    buf.get(objectBytes);

    // Execute SHA1 hash digest
    MessageDigest md = MessageDigest.getInstance("SHA1");
    byte[] shaBytes = md.digest(objectBytes);

    // Show in hex
    String shaHex = Hex.encodeHexString(shaBytes);
    System.out.println(shaHex);

上述代码输出:ce013625030ba8dba906f756967f9e9ca394464a

和 2.1 中git生成的SHA值一致,2.2 中数据结构和SHA值的生成得到验证。

2.4. 对象压缩

根据 Git-Internals-Git-Objects 可知git 对象文件是经过Zlib::Deflate.deflate 压缩存储的。

代码语言:txt
AI代码解释
复制
$ cat .git/objects/ae/a941d707291bf3f2103c096479b068f7bed4f8
x☺K
cat: write error: Input/output error

可以看到通过cat命令是无法直接输出内容的。

代码语言:txt
AI代码解释
复制
        InputStream is = new InflaterInputStream(new FileInputStream(
                ".git\\objects\\ce\\013625030ba8dba906f756967f9e9ca394464a"));

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        int b = 0;
        while ((b = is.read()) != -1) {
            baos.write(b);
        }

        byte[] res = baos.toByteArray();
        System.out.println(new String(res));

        is.close();
        baos.close();

通过如上代码可输出对象的数据结构:

代码语言:txt
AI代码解释
复制
blob 6hello

注其中包括不可见字符NUL和换行符。

通过git cat-file命令可以直接查看对象的数据内容:

代码语言:txt
AI代码解释
复制
$ git cat-file -p ce013625030ba8dba906f756967f9e9ca394464a
hello

3. 总结

  1. 对象数据结构为:
git-object-storage.png
git-object-storage.png
  1. 对象SHA值为对( 1. 对象数据结构)执行SHA1消息摘要算法生成;
  2. 对象存储结构为:对(1. 对象数据结构)进行deflate压缩后存储;

4. 参考资料

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
2 条评论
热度
最新
目前只会Git最简单的,最基础的一些命令常识,谢谢作者的整理
目前只会Git最简单的,最基础的一些命令常识,谢谢作者的整理
回复回复点赞举报
bash: irb: command not found,这个是?
bash: irb: command not found,这个是?
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
Git 对象存储结构分析
1. 前言 Git-Internals-Git-Objects | 从该文中可以了解到git 对象有:blob (数据块), tree (目录树), commit (提交)。 本文通过一个示例,以blob为例来讨论对象的存储结构。示例采用的git版本为2.17 。 2. 实践讨论 2.1. 生成Blob对象文件 首先创建一个测试git仓库 $ mkdir hello $ cd hello $ git init 然后通过创建一个文件 test,test的内容为 "hello", 可以看到test文件的字节
囚兔
2018/05/30
5500
10.2 Git 内部原理 - Git 对象
Git 是一个内容寻址文件系统。 看起来很酷, 但这是什么意思呢? 这意味着,Git 的核心部分是一个简单的键值对数据库(key-value data store)。 你可以向该数据库插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次检索(retrieve)该内容。 可以通过底层命令 hash-object 来演示上述效果——该命令可将任意数据保存于 .git 目录,并返回相应的键值。 首先,我们需要初始化一个新的 Git 版本库,并确认 objects 目录为空:
shaonbean
2019/05/26
8050
git原理和技巧
eg: 在一个目录下创建项目,使用git init初始化,并生成两个文件,使用git add添加到暂存区。
doper
2022/09/26
3570
git原理和技巧
Git 内部原理之 Git 对象哈希
在上一篇文章中,将了数据对象、树对象和提交对象三种Git对象,每种对象会计算出一个hash值。那么,Git是如何计算出Git对象的hash值?本文的内容就是来解答这个问题。
用户1257393
2018/07/30
1.4K0
Git 原理入门
即使天天使用它,很多人也未必了解它的原理。Git 为什么可以管理版本?git add、git commit这些基本命令,到底在做什么,你说得清楚吗?
ruanyf
2018/10/11
7430
Git 原理入门
终于有人把 Git 的数据模型讲清楚了!
上一篇,我们讲了 Git 的前世今生,神——Linus在 10 天内就创造了 Git 的第一版,这一篇,我们来探究一下 Git 的数据模型。
沉默王二
2021/12/23
7850
这才是真正的Git——Git内部原理揭秘!
本文作者:lzaneli,腾讯 TEG 前端开发工程师 本文以一个具体例子结合动图介绍了Git的内部原理,包括Git是什么储存我们的代码和变更历史的、更改一个文件时,Git内部是怎么变化的、Git这样实现的有什么好处等等。 通过例子解释清楚上面这张动图,让大家了解Git的内部原理。如果你已经能够看懂这张图了,下面的内容可能对你来说会比较基础。 视频链接: https://www.bilibili.com/video/av77252063 PPT 链接: https://www.lzane.com/
腾讯技术工程官方号
2019/12/18
1.6K0
这才是真正的Git——Git内部原理揭秘!
源码解析:Git的第一个提交是什么样的?
导读:经过不断地迭代,如今Git的功能越来越完善和强大。然而Git的第一个提交源码仅约1000行,当时的Git实现了哪些功能?本文将从源码开始,分析其核心思想,挖掘背后优秀的设计原理。
用户6543014
2020/09/24
2K0
源码解析:Git的第一个提交是什么样的?
git数据存储结构
以前的存储仓库,采用针对改变的文件进行标记,对每个文件进行跟踪。文件改变就会记录。git采用对version进行跟踪,将改变的文件记录下来,每一版本记录一次,没有改变的文件使用上一版本的,这样存储速度快,在你上传远程的时候,也是很快的,并且在你本地也是一个仓库,每人都是分布式仓库,代码安全性高。
zhangjiqun
2024/12/16
2390
git数据存储结构
从一个实战的角度来理解 Git 原理~
我之前写了一篇文章 《深入理解 Git 》https://zhuanlan.zhihu.com/p/71577255。
DevOps时代
2020/11/03
6270
从一个实战的角度来理解 Git 原理~
Git的存储原理
Git 出现前,主流版本控制系统(SVN...)一般为基于增量(delta-based)的系统,如下图:
小江的学习日记
2024/07/27
2150
pwnhub冬季赛web
这校验了文件名后10位以上的字符是否合法,可以跨目录上传文件,但文件名=只能是 10 位以上的这些规定得分字符。
pankas
2022/12/30
6530
pwnhub冬季赛web
10 分钟重新认识 GIT
最近对 git 的底层实现异常迷恋,周末抽空用 rust 和 rocksdb 实现了一个乞丐版的 object store - 可以存储 blob,tree,commit 三种对象。之所以用 rocksdb,是因为我不太喜欢文件系统里的那些细碎的 git 对象,我也没太研究 packfile 是如何进行差分编码的,rocksdb 恰好解决了这两个不爽。本来想写篇文章讲讲我在实现过程中踩过的坑,但考虑可能大部分读者虽然每天都在用 git,却并不真正了解 git,所以我觉得有必要先通过一些例子回顾一下 git 的思想和主要的对象类型。
tyrchen
2019/12/02
5450
洞悉技术的本质-Git内部原理探索
洞悉技术的本质,可以让我们在层出不穷的框架面前仍能泰然处之。用了那么久的 Git,不懂点内部原理,那可不行!懂点原理可以让我们遇到问题的时候能够更好更快的理清解决问题的思路。
Cloud-Cloudys
2020/07/06
8540
改变世界的一次代码提交
Linux 作为最大也是最成功的开源项目,吸引了全球程序员的贡献,到目前为止,共有两万多名开发者给 Linux Kernel 提交过代码。令人惊讶的是,在项目的前十年(1991 ~ 2002)中,Linus 作为项目管理员并没有借助任何配置管理工具,而是以手工方式通过 patch 来合并大家提交的代码。倒不是说 Linus 喜欢手工处理,而是因为他对于软件配置管理工具(SCM)非常挑剔,无论是商用的 clearcase 还是开源的 cvs、svn 等都不能入他的法眼。在他看来,一个能够满足 Linux 内核项目开发使用的版本控制系统需要满足几个条件:1) 快 2)支持多分支场景(几千个分支并行开发场景) 3) 分布式 4) 能够支持大型项目。直到2002年,Linus 终于找到了一款基本满足他要求的工具——BitKeeper, 而 BitKeeper 是商业工具,他们愿意给 Linux 社区免费使用,但是需要保证遵守不得进行反编译等条款。BitKeeper 提供的默认接口显然不能满足社区用户的全部需要,一位社区开发者反编译 BitKeeper 并利用了未公开接口,这让 BitKeeper 公司撤回了免费使用的 License。不得已,Linus 利用假期十天时间,实现一款 DVCS —— Git,并推送给社区开发者们使用。
Linux阅码场
2020/10/30
8920
改变世界的一次代码提交
用了5年的Git,你竟然还不晓得它的实现原理!
作者 | 杨夕 来源 | https://zhuanlan.zhihu.com/p/53750883 越了解事物的本质就越接近真相。我发现学习Git内部是如何工作的以及Git的内部数据结构这部分内容,对于理解Git的用途和强大至关重要。若你理解了Git的思想和基本工作原理,用起来就会知其所以然,游刃有余。这是Git系列的第一篇,主要会介绍Git的特点以及内部数据结构设计,和完成一次完整提交流程的时候数据是如何变化的。 Git有什么特点? fast,scalable,distributed revision
程序猿DD
2023/04/04
3360
用了5年的Git,你竟然还不晓得它的实现原理!
pygit:足够的Git客户端创建一个repo,commit,并将自己推送到GitHub
Git因其非常简单的对象模型而闻名(其中包括) - 并且有充分的理由。学习时git我发现本地对象数据库只是目录中的一堆普通文件.git。除了index(.git/index)和pack文件(它们是可选的)之外,这些文件的布局和格式非常简单。
iOSDevLog
2018/07/25
2.4K0
这才是真正的Git——Git内部原理
linux 之父 Linus Torvalds 大家应该都知道,而 git 也是由 Linus 开发的。从 1991 年发布了第一版的 linux 内核,Linux 内核开源项目有着众多的参与者,但绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码,之前市面上也有其他的版本管理系统,比如 CSV、SVN,但是 Linus 觉得它们很蠢,直到有了 BitKeeper 才开始使用版本管理系统。
前端森林
2021/06/25
3.1K0
这才是真正的Git——Git内部原理
牛逼的Git!!!!!!!
顾名思义,版本控制系统(Version Control System)是一类用于追踪源代码改动的工具,这些工具可以帮助我们管理代码的历史记录,不仅如此,还可以让协作编码变得轻而易举。
沉默王二
2021/04/01
6550
Git内部原理介绍
git 是一个内容寻址的文件系统,其核心部分是一个简单的键值对数据库(key-value data store),可以向该数据库插入任意类型的内容,它会返回一个40位长的哈希键值。并在此基础上提供了一个版本控制系统的用户界面。
腾讯工蜂
2018/12/07
17.3K1
相关推荐
Git 对象存储结构分析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档