Git 是如何存储文件的
01、存储方式
Git 从核心上来看不过是简单地存储键值对(key-value)。它允许插入任意类型的内容,并会返回一个键值,通过该键值可以在任何时候再取出该内容。
Git 存储数据内容的方式,为每份内容生成一个文件,取得该内容与头信息的 SHA-1 校验和,创建以该校验和前两个字符为名称的子目录,并以 (校验和) 剩下 38 个字符为文件命名 (保存至子目录下)。
写入对象
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
取回对象
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
返回对象的类型
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
02、Git 对象
数据对象 blob object
树对象 tree object
解决文件名的保存问题,允许我们将多个文件组织到一起,Git 以一种类似于 UNIX 文件系统的方式存储内容,但作了些许简化。
所有内容均以树对象和数据对象的形式存储,其中树对象对应了 UNIX 中的目录项,数据对象则大致上对应了 inodes 或文件内容。 一个树对象包含了一条或多条树对象记录(tree entry),每条记录含有一个指向数据对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息。
$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib (这是一个文件夹)
你可以自己创建 tree 。通常 Git 根据你的暂存区域或 index 来创建并写入一个 tree 。因此要创建一个 tree 对象的话首先要通过将一些文件暂存从而创建一个 index 。
$ git write-tree
$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579

commit 对象
commit 对象有格式很简单:指明了该时间点项目快照的顶层树对象、作者/提交者信息(从 Git 设置的 user.name 和 user.email中获得)以及当前时间戳、一个空行,以及提交注释信息。
每一个 commit 对象都指向了你创建的树对象快照。
当你执行git add, git commit, Git其实就是保存修改了的文件的 blob,更新索引,创建 tree 对象,最后创建 commit 对象,这些 commit 对象指向了顶层 tree 对象以及先前的 commit 对象。
这三类 Git 对象 ── blob,tree 以及 commit ── 都各自以文件的方式保存在 .git/objects 目录下。

03、对象存储
Git是如何存储对象的?
构造文件头
对象类型+空格+数据内容的长度+空字节(null byte)
>> header = "blob #{content.length}\0"
=> "blob 16\000"
计算SHA-1 校验和
Git 将文件头与原始数据内容拼接起来,并计算拼接后的新内容的 SHA-1 校验和:
>> store = header + content
=> "blob 16\000what is up, doc?"
>> require 'digest/sha1'
=> true
>> sha1 = Digest::SHA1.hexdigest(store)
=> "bd9dbf5aae1a3862dd1526723246b20206e5fc37"
用 zlib 对数据内容进行压缩
在 Ruby 中可以用 zlib 库来实现。首先需要导入该库,然后用 Zlib::Deflate.deflate() 对数据进行压缩:
>> require 'zlib'
=> true
>> zlib_content = Zlib::Deflate.deflate(store)
=> "x\234K\312\311OR04c(\317H,Q\310,V(-\320QH\311O\266\a\000_\034\a\235"
将用 zlib 压缩后的内容写入磁盘
需要指定保存对象的路径 (SHA-1 值的头两个字符作为子目录名称,剩余 38 个字符作为文件名保存至该子目录中)。
>> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
=> ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37"
>> require 'fileutils'
=> true
>> FileUtils.mkdir_p(File.dirname(path))
=> ".git/objects/bd"
>> File.open(path, 'w') { |f| f.write zlib_content }
=> 32
所有的 Git 对象都以这种方式存储,惟一的区别是类型不同 ── 除了字符串 blob,文件头起始内容还可以是 commit 或 tree 。不过虽然 blob 几乎可以是任意内容,commit 和 tree 的数据却是有固定格式的。
04、参考
Git 是如何存储文件的的更多相关文章
- Git版本控制管理学习笔记2--起步
首先确保系统中已经安装了git,这里使用的linux系统. 一.命令行初步使用: 1.git命令: 列出它的选项和最常用的子命令.标准命令格式中,COMMAND代表的就是下面列出的子命令. [root ...
- 作业2:git使用
作业要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 远端库地址:https://github.com/yellow ...
- Git的初次使用
一.配置本地Git库 1.下载安装好Git,并配置自己的信息. git config --global user.name"yourname"配置你的名称 git config - ...
- 常见的Git命令
最近想着需要把工作中做一个备份,除了本地保存之外,上传到码云是个不错的选择,除了Git的一些特点外,也可以让别人看到你的代码,共同修改之类的 首先在上传到码云之前,需要学习Git的一些基础教程,包括国 ...
- GIT学习笔记(3):分支管理
GIT学习笔记(3):分支管理 何谓分支 GIT是如何存储数据的 GIT不是存储文件差异或者变化量,而是一系列文件的快照.在Git提交时,会保存一个提交(commit)对象,该对象包含一个指向暂存内容 ...
- 你知道 Git 是如何做版本控制的吗?(转)
总结:阅读这篇文章需要20分钟 本文是转载自 滴滴WebApp架构组 的一篇文章,文章讲解了神秘的.git目录下的一些文件,最终阐述了git是如何存储数据,及git分支的相关内容. git如何存储数据 ...
- Git内部原理探索
目录 前言 Git分区 .git版本库里的文件/目录是干什么的 Git是如何存储文件信息的 当我们执行git add.git commit时,Git背后做了什么 Git分支的本质是什么 HEAD引用 ...
- 深入浅出 Git
开篇 你可能遇到过 如果你遇到这个场景,那你可能需要版本控制. 什么是版本控制 版本控制最主要的功能就是追踪文件的变更.它将什么时候.什么人更改了文件的什么内容等信息忠实地了已录下来.每一次文件的改变 ...
- 版本号控制-搭建gitserver
GitHub是一个免费托管开源码的Gitserver,假设我们不想公开项目的源码,又不想付费使用.那么我们能够自己搭建一台Gitserver. 以下我们就看看,怎样在Ubuntu上搭建Gitserve ...
随机推荐
- CenOS下监控工具尝试
Cacti cacti重图形,有数据历史,需要用到数据库支持,支持web配置,默认不支持告警,可以加插件. Server端配置 安装epel yum install -y epel-release 安 ...
- Kubernetes K8S之固定节点nodeName和nodeSelector调度详解
Kubernetes K8S之固定节点nodeName和nodeSelector调度详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-mas ...
- vue--axios分装
封装: import axios from 'axios' axios.defaults.baseURL="http://127.0.0.1:8000/" axios.defaul ...
- PyQt学习随笔:自定义信号连接时报AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 如果使用自定义信号,一定要记得信号是类变量,必须在类中定义,不能在实例 ...
- 关于Python链式赋值的赋值顺序问题
在<第4.7节 Python特色的序列解包.链式赋值.链式比较>一文中,老猿这样介绍的: 链式赋值是用一行语句将多个变量赋值为同一个值,语法如下: 变量1=变量2=变量n=赋值表达式 该语 ...
- 第12.5节 Python time模块导览
一.时间相关的概念 time模块模块提供了各种时间相关的函数,在介绍时间相关功能前,先介绍一些术语和惯例: epoch 是时间开始的点,并且取决于平台.对于Unix, epoch 是1970年1月1日 ...
- PyQt(Python+Qt)学习随笔:QTreeView树形视图的autoExpandDelay属性
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTreeView树形视图的autoExpandDelay属性用于控制在视图中拖拽时,当鼠标停留在一 ...
- PyQt(Python+Qt)学习随笔:QAbstractItemView的verticalScrollMode和horizontalScrollMode属性
老猿Python博文目录 老猿Python博客地址 一.概述 verticalScrollMode和horizontalScrollMode属性用于控制视图如何在垂直方向和水平方向滚动内容.滚动可以按 ...
- secret_key伪造session来进行越权
从swpuctf里面的一道ctf题目来讲解secret_key伪造session来进行越权. 以前没有遇到过这种题目,这次遇到了之后查了一些资料把它做了出来,记录一下知识点. 参考资料 http:// ...
- H5相关知识点整理
01-HTML5基础 了解HTML5 ☞HTML5属于上一代HTML的新迭代语言,设计HTML5最主要的目的是为了在移动设备上支持多媒体!!! 例如: video 标签和 audio 及 canvas ...