1. 前言
2. git 是如何保存代码的
3. hash 算法
4. 暂存区

1. 前言


我使用的是 mac 系统,本文用到 ​​tree​​​、​​watch​​ 命令,mac 默认是没有这两个命令的,需要先安装下这两个命令



  1. ​brew install tree && brew install watch​

2. git 是如何保存代码的


一、git 在 add 时,会将文件的内容通过Hash SHA-1算法生成一个基于Hash值的键值对数据库

参考 git 中文书籍​​git对象​​​章节: ​​Pro Git 中文版(第二版)​

监听文件变化可使用命令(每隔一秒执行 tree .git 命令):



  1. ​watch -n -1 -d tree .git​

创建 ​​hello.txt​​​ 文件,文件内容: ​​hello git​



  1. ​echo 'hello git' > hello.txt​

将文件添加到暂存区, 此时 ​​.git/objects​​ 下面会多出一个目录,这个目录下存放一个文件

git 会根据文件内容通过 hash sha-1 算法得到40位的 blob对象 hash字符串文件

示例: ​​8d0e41234f24b6da002d962a26c2495ea16a425f​​, 前两位作为目录名,后38位作为文件名进行存储

这个文件存储的就是 hello.txt 的文件内容: ​​hello git​​, 下面就来验证这句话



  1. ​git add hello.txt​

git 原理初探_git

使用 ​​cat​​​ 查看 hash 串存储的文件内容,看到是一串乱码,这个是文件经过​​zlib​​ 压缩后的数据



  1. ​cat .git/objects/xx/xxxx​

git 原理初探_git_02

查看文件的原始内容,压缩前的数据:

语法格式: ​​git cat-file -p 索引值前七位​

cat: 可以理解查看 -p: pretty 漂亮的,理解为便于查看的



  1. ​git cat-file -p 8d0e412​

git 原理初探_git_03

查看文件类型,执行以下命令返回 ​​blob​​​ 代表是 ​​blob对象​



  1. ​git cat-file -t 8d0e412​

查看文件内容长度(例如: 10)



  1. ​git cat-file -s 8d0e412​

3. hash 算法


hash算法: 将任意长度的内容通过算法生成固定长度的输出,也就是加密为固定长度的字符串

git 是一个基于Hash值的键值对数据库,键指的是​​hash索引值​​​,值指的 ​​hash索引值对应的文件内容​

总结: git 的核心一个键值对数据库,里面有一种叫 ​​blob​​ 的数据对象负责存储压缩后的代码

具体算法,使用算法生成 hash 字符串

语法格式



  1. ​'blob 长度\0内容'​

使用示例

  • 10: 是文件的长度, 除了hello git 9个字符外, 还有一个\n, 所以长度为10
  • hello git 是文件的内容
  • sha1sum: 是Linux自带的计算Hash串的命令


  1. ​echo 'blob 10\0hello git' | shasum​


  1. ​注意​

  2. ​如果在windows下, 可能会得到不同的结果.​

  3. ​因为在windows下, 文件的末尾添加的是 CRLF 也就是 \r\n, 而 Linux下只有 \n​

  4. ​因此, 可能会得出不一样的结果​

4. 暂存区


暂存区所在位置: ​​.git/index​

暂存区可以看做一个文件名到 blob 对象的索引表,这也是为什么暂存区叫 ​​index​​ 的原因

查看暂存区中的数据



  1. ​git ls-files -s​