git是如何存储信息的
1、初始化仓库,新建文件,并添加到暂存区
git init
echo '111' > a.txt
echo '222' > b.txt
git add *.txt
// 查看一下当前的git仓库中的内容
tree .git
├─hooks
├─info
├─objects
│ ├─4e
│ ├─71
│ ├─info
│ └─pack
└─refs
├─heads
└─tags
ls -a .git/objects/4e
./ ../ f5d11d3b99f88fb9f70b694de01db16c56ed50
ls -a .git/objects/71
./ ../ 70f7d93c37a8861f0e6816780b2881ad5f58d2
// 查看一下f5d11d3b99f88fb9f70b694de01db16c56ed50文件中的内容
cat .git/objects/4e/f5d11d3b99f88fb9f70b694de01db16c56ed50
x☺K□□OR0gP744TW□☻∟.♥☻
// 打印出来的是一些乱码,原因是因为git对储存的内容做了二进制压缩
2、cat-file
git cat-file [-t] [-p]
-t 打印文件类型
-p 打印文件具体内容
git cat-file -t 4ef5d1
blob
git cat-file -p 4ef5d1
'111'
3、git object
git 储存信息的最小单元,对象数据库包含四类对象。git对象创建完成后均不可变更。
- Blob:包含二进制数据,它们是文件内容。只要文件内容改变,就会在对象数据库中生成一个blob对象。注意,blob对象只保存文件内容,不含文件名和文件存储位置等信息。如果文件名改变,或者文件储存位置改变,不会生成新的blob对象。
- Tree:blob对象的集合,以及它们的文件名和权限。一个tree对象描述一个时点上的一个目录。
- Commit:描述一个时点上的项目状态,包含一条log信息,一个tree对象和指向父节点(parent commits)的指针。第一个commit对象没有父节点。
- 记录 root tree SHA1
- 记录 parent commit SHA1
- 记录作者、时间和 commit message
- tag
4、sha1哈希算法
111 -> 4ef5d11d3b99f88fb9f70b694de01db16c56ed50
每个git对象都有一个哈希值,哈希值可以理解为我们的身份证号
4ef5d11d3b99f88fb9f70b694de01db16c56ed50
就是内容为111类型为blob的git对象的身份证号,我们可以通过4ef5d11d3b99f88fb9f70b694de01db16c56ed50找到这个git对象
5、git commit
git commit -m 'init'
tree .git
├─hooks
├─info
├─logs
│ └─refs
│ └─heads
├─objects
│ ├─39
│ ├─4e
│ ├─5f
│ ├─71
│ ├─info
│ └─pack
└─refs
├─heads
└─tags
ls -a .git/objects/39
./ ../ bd985025d281e7c1d1c9493c90156fb9e26ea0
ls -a .git/objects/5f
./ ../ 3f16e16db5faec1bf71fab36cbad24fbddfd39
git cat-file -t 5f3f16
tree
git cat-file -p 5f3f16
100644 blob 4ef5d11d3b99f88fb9f70b694de01db16c56ed50 a.txt
100644 blob 7170f7d93c37a8861f0e6816780b2881ad5f58d2 b.txt
git cat-file -t 39bd98
commit
git cat-file -p 39bd98
tree 5f3f16e16db5faec1bf71fab36cbad24fbddfd39
6、HEAD指针和分支
cat .git/HEAD
ref: refs/heads/master
cat .git/refs/heads/master
39bd985025d281e7c1d1c9493c90156fb9e26ea0
可以看出,HEAD指针指向分支指针,分支指针指向最新的commit
HEAD、分支、普通的Tag可以简单的理解成是一个指针,指向对应commit的SHA1值。
7、为什么要把文件的权限和文件名储存在Tree object里面而不是Blob object呢?
因为更改一个文件名就需要新建一个Blob object,假如文件很大的话,会很占空间,而Tree object体积相对很小
8、当你修改了其中一个文件,创建一个新的commit后
git的三个分区
- 工作目录 ( working directory ):操作系统上的文件,所有代码开发编辑都在这上面完成。
- 索引( index or staging area ):可以理解为一个暂存区域,这里面的代码会在下一次commit被提交到Git仓库。
- Git仓库( git repository ):由Git object记录着每一次提交的快照,以及链式结构记录的提交变更历史。
转载
李泽帆
https://www.lzane.com/tech/git-internal/