本文主要探讨git 的add commit 操作的数据是如何进行记录的
1. 新建一个git仓库
chuangchuang@chuang:~/work/temp$ cd gittest/
chuangchuang@chuang:~/work/temp/gittest$ ll
总用量 8
drwxrwxr-x 2 chuangchuang chuangchuang 4096 11月 11 18:20 ./
drwxrwxr-x 4 chuangchuang chuangchuang 4096 11月 11 18:20 ../
chuangchuang@chuang:~/work/temp/gittest$ git init
初始化空的 Git 仓库于 /home/chuangchuang/work/temp/gittest/.git/
chuangchuang@chuang:~/work/temp/gittest$
chuangchuang@chuang:~/work/temp/gittest$ ll
总用量 12
drwxrwxr-x 3 chuangchuang chuangchuang 4096 11月 11 18:21 ./
drwxrwxr-x 4 chuangchuang chuangchuang 4096 11月 11 18:20 ../
drwxrwxr-x 7 chuangchuang chuangchuang 4096 11月 11 18:21 .git/
2.看一下.git的结构
chuangchuang@chuang:~/work/temp/gittest$ tree .git/
.git/
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
9 directories, 13 files
3,添加一些东西
3.1 刚开始的时候并没有在路径上显示分支,即使使用git branch -a 也没有
chuangchuang@chuang:~/work/temp/gittest$ git branch -a
chuangchuang@chuang:~/work/temp/gittest$
3.2 在往里面添加过文件
chuangchuang@chuang:~/work/temp/gittest$ touch aa.txt //1
chuangchuang@chuang:~/work/temp/gittest$ ll //2
总用量 12
drwxrwxr-x 3 chuangchuang chuangchuang 4096 11月 11 19:00 ./
drwxrwxr-x 4 chuangchuang chuangchuang 4096 11月 11 18:20 ../
-rw-rw-r-- 1 chuangchuang chuangchuang 0 11月 11 19:00 aa.txt
drwxrwxr-x 7 chuangchuang chuangchuang 4096 11月 11 19:00 .git/
3.3 查看.git目录(只有objects目录有变化)
├── objects
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── info
│ └── pack
这个时候发现在objects下面多了一个id e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
查看该文件下有什么
chuangchuang@chuang:~/work/temp/gittest[master*]$ git cat-file -p e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
chuangchuang@chuang:~/work/temp/gittest[master*]$
//显示的是什么都没有,这个是add 添加到stage区的文件,因为是空文件,所以没有内容
3.4 执行了commit 操作以后就有了分支
chuangchuang@chuang:~/work/temp/gittest$ git add aa.txt //1
chuangchuang@chuang:~/work/temp/gittest$ git commit -a -m "aa.txt tianjia" //2
[master (根提交) a3c8eff] aa.txt tianjia
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 aa.txt
// 接下来的路径中就显示了master分支
chuangchuang@chuang:~/work/temp/gittest[master*]$ ll //3
总用量 12
drwxrwxr-x 3 chuangchuang chuangchuang 4096 11月 11 19:00 ./
drwxrwxr-x 4 chuangchuang chuangchuang 4096 11月 11 18:20 ../
-rw-rw-r-- 1 chuangchuang chuangchuang 0 11月 11 19:00 aa.txt
drwxrwxr-x 8 chuangchuang chuangchuang 4096 11月 11 19:00 .git/
4,再次看看.git中都有写什么
.git
├── branches
├── objects
│ ├── a3
│ │ └── c8effc24eeb66de97a66b073c6d62c48fbc9ed
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f1
│ │ └── 3f51556efabe074d5b255eabcdd3ec33520c55
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
4.1 可以看到object中多了两个目录,每个目录下多了一个文件,这个其实就是每次操作的hash值
执行git log 看看当前有多少提交
chuangchuang@chuang:~/work/temp/gittest[master*]$ git log -1 --pretty=raw //注意这里的是 -1 是数字不是字母
commit a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
tree f13f51556efabe074d5b255eabcdd3ec33520c55
author chuang <chuangchuang.chen@cafintech.com> 1510398041 +0800
committer chuang <chuangchuang.chen@cafintech.com> 1510398041 +0800
aa.txt tianjia
chuangchuang@chuang:~/work/temp/gittest[master*]$ git version
可以看到有一个commit id ,是 a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
还有一个是本次操作的快照id f13f51556efabe074d5b255eabcdd3ec33520c55
使用git cat-file解压文件看一下
//可以看到这个里面存储的就是commit 提交的时候填入的信息
chuangchuang@chuang:~/work/temp/gittest[master*]$ git cat-file -p a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
tree f13f51556efabe074d5b255eabcdd3ec33520c55
author chuang <chuangchuang.chen@cafintech.com> 1510398041 +0800
committer chuang <chuangchuang.chen@cafintech.com> 1510398041 +0800
aa.txt tianjia
// 这个tree中存放的也是一个引用,指向了真正存放文件内容 的文件
chuangchuang@chuang:~/work/temp/gittest[master*]$ git cat-file -p f13f51556efabe074d5b255eabcdd3ec33520c55
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 aa.txt
//因为这个文件刚刚创建,什么都没有
chuangchuang@chuang:~/work/temp/gittest[master*]$ git cat-file -p e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
chuangchuang@chuang:~/work/temp/gittest[master*]$
//查看一下仓库中的文件记录,就是最开始add的那个id
chuangchuang@chuang:~/work/temp/gittest[master*]$ git ls-tree -l HEAD
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 aa.txt
可以看到文件记录是e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
这个代表了仓库中存储的该原始文件
5 执行git add 操作后的结构
chuangchuang@chuang:~/work/temp/gittest[master*]$ echo '1 di yi ci wang li tian jia nei rong' >> aa.txt
chuangchuang@chuang:~/work/temp/gittest[master*]$ git add .
chuangchuang@chuang:~/work/temp/gittest[master*]$ git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
修改: aa.txt
这个时候再看
chuangchuang@chuang:~/work/temp/gittest[master*]$ tree .git/
.git/
├── branches
├── objects
│ ├── a3
│ │ └── c8effc24eeb66de97a66b073c6d62c48fbc9ed
│ ├── e4
│ │ └── 626567ec9ae5a6f3abd77af37c25a85ec4e7f1
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f1
│ │ └── 3f51556efabe074d5b255eabcdd3ec33520c55
│ ├── info
│ └── pack
可以看到多了一个文件
e4626567ec9ae5a6f3abd77af37c25a85ec4e7f1
通过list-files 查看缓存区的文件
chuangchuang@chuang:~/work/temp/gittest[master*]$ git ls-files -s
100644 e4626567ec9ae5a6f3abd77af37c25a85ec4e7f1 0 aa.txt
6,再次执行git commit 后的结果
6.1 执行commit
chuangchuang@chuang:~/work/temp/gittest[master*]$ git commit -a -m "di er ci ti jiao test"
[master 45776d6] di er ci ti jiao test
1 file changed, 1 insertion(+)
6.2 查看.git 的object目录为(截取了一部分)
├── objects
│ ├── 45
│ │ └── 776d6cb67571cfe31656fb1d114e520c9e0ab2
│ ├── 68
│ │ └── d98b1781c29d1df8b4ac7b6d457bccecf9756e
│ ├── a3
│ │ └── c8effc24eeb66de97a66b073c6d62c48fbc9ed
│ ├── e4
│ │ └── 626567ec9ae5a6f3abd77af37c25a85ec4e7f1
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f1
│ │ └── 3f51556efabe074d5b255eabcdd3ec33520c55
│ ├── info
│ └── pack
可以看到又多了两条记录
6.3 通过git log查看commit
chuangchuang@chuang:~/work/temp/gittest[master*]$ git log -2 --pretty=raw
commit 45776d6cb67571cfe31656fb1d114e520c9e0ab2 //这个是第二次提交产生的commit id
tree 68d98b1781c29d1df8b4ac7b6d457bccecf9756e // 这个是第二次提交产生的快照
parent a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
author chuang <chuangchuang.chen@cafintech.com> 1510452772 +0800
committer chuang <chuangchuang.chen@cafintech.com> 1510452772 +0800
di er ci ti jiao test
commit a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
tree f13f51556efabe074d5b255eabcdd3ec33520c55
author chuang <chuangchuang.chen@cafintech.com> 1510398041 +0800
committer chuang <chuangchuang.chen@cafintech.com> 1510398041 +0800
aa.txt tianjia
6.3.1 git log 分析
45776d6cb67571cfe31656fb1d114e520c9e0ab2
是这次commit 产生的commit id
68d98b1781c29d1df8b4ac7b6d457bccecf9756e
是本次提交的快照
parent a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
表明了上次提交的 commit id 是a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
对应了第一次提交的commit id
6.3.2 查看当前本地仓库的文件
chuangchuang@chuang:~/work/temp/gittest[master*]$ git ls-tree -l HEAD
100644 blob e4626567ec9ae5a6f3abd77af37c25a85ec4e7f1 37 aa.txt
是保存id 为e4626567ec9ae5a6f3abd77af37c25a85ec4e7f1 的文件
这个对应了5中add操作在object目录下产生的id,说明这个时候已经从暂存区(stage)进入了仓库
6.3.3 分析这些id之间的关系
//这里可以看出,commit id中存储的就是 commit的时候填写进去的信息
chuangchuang@chuang:~/work/temp/gittest[master*]$ git cat-file -p 45776d6cb67571cfe31656fb1d114e520c9e0ab2
tree 68d98b1781c29d1df8b4ac7b6d457bccecf9756e
parent a3c8effc24eeb66de97a66b073c6d62c48fbc9ed
author chuang <chuangchuang.chen@cafintech.com> 1510452772 +0800
committer chuang <chuangchuang.chen@cafintech.com> 1510452772 +0800
di er ci ti jiao test
// tree中记录的依然是一个指针,指向了blob类型的 e4626567ec9ae5a6f3abd77af37c25a85ec4e7f1
chuangchuang@chuang:~/work/temp/gittest[master*]$ git cat-file -p 68d98b1781c29d1df8b4ac7b6d457bccecf9756e
100644 blob e4626567ec9ae5a6f3abd77af37c25a85ec4e7f1 aa.txt
//可以看到这个里面存储的是真正的文件内容,也就是add操作产生的id
chuangchuang@chuang:~/work/temp/gittest[master*]$ git cat-file -p e4626567ec9ae5a6f3abd77af37c25a85ec4e7f1
1 di yi ci wang li tian jia nei rong
7 ,一次添加多个文件
7.1 两次修改原来的aa.txt
//第一次操作,修改aa.txt 会产生一个新的index id
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ echo 'another test san'>> aa.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ cat aa.txt
1 di yi ci wang li tian jia nei rong
another test san
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git add .
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git ls-files -s
100644 5c3079aa5ec819e560b4b548e0ea4efb39be239f 0 aa.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git cat-file -p 5c3079aa5ec819e560b4b548e0ea4efb39be239f
//第二次操作修改 aa.txt 会产生新的 index id
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ echo 'third test'>>aa.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ cat aa.txt
1 di yi ci wang li tian jia nei rong
another test san
third test
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git add .
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git ls-files -s
100644 658bed4dcaeec2c18e04af192971e7093b3c7ab9 0 aa.txt
7.2 添加3个文件,
//添加bb.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ touch bb.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ echo 'bb text'>> bb.txt
//添加cc.txt dd.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ vi cc.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ vi dd.txt
7.3 查看缓冲区index
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git ls-files -s
100644 658bed4dcaeec2c18e04af192971e7093b3c7ab9 0 aa.txt
100644 90593bc026fb525e8bf56485d3101a389dac4417 0 bb.txt
100644 9af3475341efe72b1fc0b4109055436b2700c1b9 0 cc.txt
100644 f224fbe59efc4467313afe938f836488d84ff3b3 0 dd.txt
可以看到每个文件分别有一条
7.4 执行commit之后的git log结构
commit
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git commit -m "一次提交了四个"
[dev d4a8da9] 一次提交了四个
4 files changed, 5 insertions(+)
create mode 100644 bb.txt
create mode 100644 cc.txt
create mode 100644 dd.txt
查看仓库
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git ls-tree -l HEAD
100644 blob 658bed4dcaeec2c18e04af192971e7093b3c7ab9 65 aa.txt
100644 blob 90593bc026fb525e8bf56485d3101a389dac4417 8 bb.txt
100644 blob 9af3475341efe72b1fc0b4109055436b2700c1b9 12 cc.txt
100644 blob f224fbe59efc4467313afe938f836488d84ff3b3 8 dd.txt
chuangchuang@chuang:~/work/temp/tempgit[dev*]$
查看日志
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git log -1 --pretty=raw
commit d4a8da99076957a318aafff68fab06f81862fafc
tree bfdc957c7bb165a8f53c13b49261c683ca5c8c7f
parent 45776d6cb67571cfe31656fb1d114e520c9e0ab2
author chuang <chuangchuang.chen@cafintech.com> 1510484509 +0800
committer chuang <chuangchuang.chen@cafintech.com> 1510484509 +0800
7.5 分别看看该次commit的 log 记录对应结构
查看commit
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git cat-file -p d4a8da99076957a318aafff68fab06f81862fafc
tree bfdc957c7bb165a8f53c13b49261c683ca5c8c7f
parent 45776d6cb67571cfe31656fb1d114e520c9e0ab2
author chuang <chuangchuang.chen@cafintech.com> 1510484509 +0800
committer chuang <chuangchuang.chen@cafintech.com> 1510484509 +0800
一次提交了四个
查看 commit对应的tree,也就是当次操作的快照
chuangchuang@chuang:~/work/temp/tempgit[dev*]$ git cat-file -p bfdc957c7bb165a8f53c13b49261c683ca5c8c7f
100644 blob 658bed4dcaeec2c18e04af192971e7093b3c7ab9 aa.txt
100644 blob 90593bc026fb525e8bf56485d3101a389dac4417 bb.txt
100644 blob 9af3475341efe72b1fc0b4109055436b2700c1b9 cc.txt
100644 blob f224fbe59efc4467313afe938f836488d84ff3b3 dd.txt
可以看到,这里的快照的id关联的 index的id是刚才add操作产生的四个id
8 总结
git的数据信息的管理都是在.git/objects目录下进行管理的
git的add
- 会在object下
为每一个变化的文件产生一个压缩文件来记录改变后的文件(是改变后的完整文件)
commit 操作
- 产生一个commit id记录本次commit的一些描述性信息
- 产生一个关联commit的快照信息的文件
- 2中产生的文件内容包含指向add产生的压缩文件的指针