本文将主要介绍blob
对象,tree
对象,commit
对象,tag
对象
.git核心
.git/HEAD
:一般情况下,指向分支引用
;如果直接指向提交对象
,将处于detached HEAD
状态
.git/index
:暂存区
信息
.git/objects
:Git对象
数据
.git/refs
:引用
信息,包括分支引用
,标签引用
等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 $ git log --oneline --decorate --graph --all * ae432e4 (HEAD -> master) echo master > file * daa44e8 add file $ ls .git branches COMMIT_EDITMSG config description HEAD hooks index info logs objects ORIG_HEAD refs rr-cache $ cat .git/HEAD ref: refs/heads/master $ cat .git/refs/heads/master ae432e46c21f45991f18eeac8586da367134bff7 $ git checkout HEAD~ Note: checking out 'HEAD~'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at daa44e8... add file $ ➦ daa44e8 cat .git/HEAD # ref a commit object , not a branch ref -> 'detached HEAD' state daa44e833989e82b1f41d12fea5dd391b163bce6 $ ➦ daa44e8 cat .git/refs/heads/master ae432e46c21f45991f18eeac8586da367134bff7 $ ➦ daa44e8 git checkout master Previous HEAD position was daa44e8... add file Switched to branch 'master' $ $ cat .git/HEAD ref: refs/heads/master $ ls .git/objects 08 1f ae da df e6 info pack
blob对象
blob对象
:存储**实际的文件内容
**
hash-object -w
:计算object ID
,并写入object database
(即.git/objects
)
cat-file -p
:显示Git对象信息
cat-file -t
:显示Git对象类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 $ git init Initialized empty Git repository in /home/zhongmingmao/demo/.git/ $ find .git/objects .git/objects .git/objects/info .git/objects/pack $ find .git/objects -type f # no objects , stdout printed nothing $ echo 'zhongmingmao' | git hash-object -w --stdin # write blob object to object database b98963d686f67040f88c58be271b1ef7541d5ec0 $ git cat-file -p b98963d686f67040f88c58be271b1ef7541d5ec0 zhongmingmao $ git cat-file -t b98963d686f67040f88c58be271b1ef7541d5ec0 blob $ echo 'v1' > zhongmingmao.txt $ git hash-object -w zhongmingmao.txt 626799f0f85326a8c1fc522db584e86cdfccd51f $ echo 'v2' > zhongmingmao.txt $ git hash-object -w zhongmingmao.txt 8c1384d825dbbe41309b7dc18ee7991a9085c46e $ find .git/objects -type f .git/objects/b9/8963d686f67040f88c58be271b1ef7541d5ec0 .git/objects/62/6799f0f85326a8c1fc522db584e86cdfccd51f .git/objects/8c/1384d825dbbe41309b7dc18ee7991a9085c46e $ git cat-file -p 626799f0f85326a8c1fc522db584e86cdfccd51 v1 $ git cat-file -p 8c1384d825dbbe41309b7dc18ee7991a9085c46e v2 $ git cat-file -t 8c1384d825dbbe41309b7dc18ee7991a9085c46e blob
tree对象
tree对象
:主要用于**组织多个文件
**,类似于目录的作用
$branch^{tree}
:分支引用的commit对象
所指向的tree对象
update-index
:将文件内容注册到index
--add
:将不存在于index
的文件添加到index
--cacheinfo
:将object database
(.git/objects
)的文件添加到index
write-tree
:将index
的当前内容创建一个tree
对象,相当于保存快照
read-tree --prefix
:将一个已存在的tree
对象写入index
,指定子目录前缀
创建第1个tree对象904970
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 $ git init Initialized empty Git repository in /home/zhongmingmao/demo/.git/ $ echo 'v1' > zhongmingmao.txt $ git hash-object -w zhongmingmao.txt $ find .git/objects -type f .git/objects/62/6799f0f85326a8c1fc522db584e86cdfccd51f $ gst -sb ## Initial commit on master ?? zhongmingmao.txt # add zhongmingmao.txt(v1) to index from git object database $ git update-index --add --cacheinfo 100644 626799f0f85326a8c1fc522db584e86cdfccd51f zhongmingmao.txt $ gst -sb ## Initial commit on master A zhongmingmao.txt $ find .git/objects -type f .git/objects/62/6799f0f85326a8c1fc522db584e86cdfccd51f $ git write-tree # create tree object from index 904970fc7917a1f77fff8280298cb54da4bd89c2 $ find .git/objects -type f .git/objects/62/6799f0f85326a8c1fc522db584e86cdfccd51f .git/objects/90/4970fc7917a1f77fff8280298cb54da4bd89c2 $ git cat-file -p 904970fc7917a1f77fff8280298cb54da4bd89c2 100644 blob 626799f0f85326a8c1fc522db584e86cdfccd51f zhongmingmao.txt $ git cat-file -t 904970fc7917a1f77fff8280298cb54da4bd89c2 tree
创建第2个tree对象dec4f9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 $ echo 'v2' > zhongmingmao.txt $ gst -sb ## Initial commit on master AM zhongmingmao.txt # replace zhongmingmao.txt(v2) of zhongmingmao(v1) in index from working directory $ git update-index zhongmingmao.txt $ gst -sb ## Initial commit on master A zhongmingmao.txt $ touch README.md $ git update-index --add README.md # add README.md to index from working diectory $ gst -sb ## Initial commit on master A README.md A zhongmingmao.txt $ git write-tree dec4f9365e77576c0a95cd1938a50e71a9f7a6b6 $ git cat-file -p dec4f9365e77576c0a95cd1938a50e71a9f7a6b6 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 README.md 100644 blob 8c1384d825dbbe41309b7dc18ee7991a9085c46e zhongmingmao.txt $ git cat-file -p 8c1384d825dbbe41309b7dc18ee7991a9085c46e v2
创建第3个tree对象aff674
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 $ git read-tree --prefix=v1 904970fc7917a1f77fff8280298cb54da4bd89c2 # read tree(904970) to index as subdir 'v1' $ gst -sb ## Initial commit on master A README.md AD v1/zhongmingmao.txt A zhongmingmao.txt $ git write-tree aff6742443246bc0e9df32727ce0e5ee27de3b1c $ git cat-file -p aff6742443246bc0e9df32727ce0e5ee27de3b1c 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 README.md 040000 tree 904970fc7917a1f77fff8280298cb54da4bd89c2 v1 100644 blob 8c1384d825dbbe41309b7dc18ee7991a9085c46e zhongmingmao.txt $ git checkout -- v1 $ gst -sb ## Initial commit on master A README.md A v1/zhongmingmao.txt A zhongmingmao.txt $ ls * README.md zhongmingmao.txt v1: zhongmingmao.txt $ cat zhongmingmao.txt v2 $ cat v1/zhongmingmao.txt v1 $ git commit -m 'init commit' [master (root-commit) bd32670] init commit 3 files changed, 2 insertions(+) create mode 100644 README.md create mode 100644 v1/zhongmingmao.txt create mode 100644 zhongmingmao.txt $ git cat-file -p master^{tree} 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 README.md 040000 tree 904970fc7917a1f77fff8280298cb54da4bd89c2 v1 100644 blob 8c1384d825dbbe41309b7dc18ee7991a9085c46e zhongmingmao.txt $ git cat-file -p HEAD^{tree} 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 README.md 040000 tree 904970fc7917a1f77fff8280298cb54da4bd89c2 v1 100644 blob 8c1384d825dbbe41309b7dc18ee7991a9085c46e zhongmingmao.txt $ git cat-file -p bd32670^{tree} 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 README.md 040000 tree 904970fc7917a1f77fff8280298cb54da4bd89c2 v1 100644 blob 8c1384d825dbbe41309b7dc18ee7991a9085c46e zhongmingmao.txt
commit对象
commit
对象,指向一个tree
对象,相当于一个快照
commit-tree $tree_object -p $commit_object
:创建提交对象
依次创建3个tree
对象:90497
,dec4f9
,aff674
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 $ git init Initialized empty Git repository in /home/zhongmingmao/demo/.git/ $ echo 'v1' > zhongmingmao.txt $ git hash-object -w zhongmingmao.txt 626799f0f85326a8c1fc522db584e86cdfccd51f $ git update-index --add --cacheinfo 100644 626799f0f85326a8c1fc522db584e86cdfccd51f zhongmingmao.txt $ git write-tree 904970fc7917a1f77fff8280298cb54da4bd89c2 $ echo 'v2' > zhongmingmao.txt $ git update-index zhongmingmao.txt $ touch README.md $ git update-index --add README.md $ git write-tree dec4f9365e77576c0a95cd1938a50e71a9f7a6b6 $ git read-tree --prefix=v1 904970fc7917a1f77fff8280298cb54da4bd89c2 $ git checkout -- v1 $ git write-tree aff6742443246bc0e9df32727ce0e5ee27de3b1c $ gst -sb ## Initial commit on master A README.md A v1/zhongmingmao.txt A zhongmingmao.txt
创建第1个commit
对象63dacd
,关于.git/HEAD
和.git/refs/heads/master
属于Git引用
的内容,后续补充
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 $ git commit-tree 904970 -m '1st commit' 63dacdf39138700e82649e7ead745e2a9322d926 $ git cat-file -p 63dacd tree 904970fc7917a1f77fff8280298cb54da4bd89c2 author zhongmingmao <[email protected] > 1492596559 +0800 committer zhongmingmao <[email protected] > 1492596559 +0800 1st commit $ gst -sb ## Initial commit on master A README.md A v1/zhongmingmao.t $ cat .git/HEAD ref: refs/heads/master $ echo '63dacdf39138700e82649e7ead745e2a9322d926' > .git/refs/heads/master $ gst -sb ## master A README.md A v1/zhongmingmao.txt M zhongmingmao.txt $ git diff --cached zhongmingmao.txt diff --git a/zhongmingmao.txt b/zhongmingmao.txt index 626799f..8c1384d 100644 --- a/zhongmingmao.txt +++ b/zhongmingmao.txt @@ -1 +1 @@ -v1 +v2 $ git log --oneline --decorate --graph --all * 63dacdf (HEAD -> master) 1st commit
创建第2个commit
对象1eb9faf
1 2 3 4 5 6 7 8 9 10 11 12 $ git commit-tree dec4f9 -p 63dacdf -m '2nd commit' 1eb9faf3eff1ae9018a223a0a74b9e86ad7f5523 $ echo '1eb9faf3eff1ae9018a223a0a74b9e86ad7f5523' > .git/refs/heads/master $ gst -sb ## master A v1/zhongmingmao.txt $ git log --oneline --decorate --graph --all * 1eb9faf (HEAD -> master) 2nd commit * 63dacdf 1st commit
创建第3个commit
对象5fbdcc4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ git commit-tree aff674 -p 1eb9faf -m '3rd commit' 5fbdcc4c76301f9a1c80bdd44ba1c18c1410dc21 $ echo '5fbdcc4c76301f9a1c80bdd44ba1c18c1410dc21' > .git/refs/heads/master $ gst On branch master nothing to commit, working directory clean $ git log --oneline --decorate --graph --all * 5fbdcc4 (HEAD -> master) 3rd commit * 1eb9faf 2nd commit * 63dacdf 1st commit $ git cat-file -p 5fbdcc4 tree aff6742443246bc0e9df32727ce0e5ee27de3b1c parent 1eb9faf3eff1ae9018a223a0a74b9e86ad7f5523 author zhongmingmao <[email protected] > 1492597186 +0800 committer zhongmingmao <[email protected] > 1492597186 +0800 3rd commit
tag对象
只有annotated tag
才会创建tag
对象,lightweight tag
直接指向commit
对象
lightweight tag 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ git log --oneline --decorate --graph --all * 5fbdcc4 (HEAD -> master) 3rd commit * 1eb9faf 2nd commit * 63dacdf 1st commit $ git tag v1.0 1eb9faf # just point to a commit object directly , no tag object $ git log --oneline --decorate --graph --all * 5fbdcc4 (HEAD -> master) 3rd commit * 1eb9faf (tag: v1.0) 2nd commit * 63dacdf 1st commit $ git show --oneline -s v1.0 1eb9faf 2nd commit $ cat .git/refs/tags/v1.0 1eb9faf3eff1ae9018a223a0a74b9e86ad7f5523 $ git cat-file -t 1eb9faf3eff1ae9018a223a0a74b9e86ad7f5523 commit
annotated tag 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 $ git log --oneline --decorate --graph --all * 5fbdcc4 (HEAD -> master) 3rd commit * 1eb9faf (tag: v1.0) 2nd commit * 63dacdf 1st commit $ git tag -a v2.0 -m 'tag 2.0' # create a annotated tag object which point to a commit object $ git log --oneline --decorate --graph --all * 5fbdcc4 (HEAD -> master, tag: v2.0) 3rd commit * 1eb9faf (tag: v1.0) 2nd commit * 63dacdf 1st commit $ git show --oneline -s v2.0 tag v2.0 tag 2.0 5fbdcc4 3rd commit $ cat .git/refs/tags/v2.0 8a4e71ed97d18b9ad3a83850eef09a2c651e0e01 $ git cat-file -p 8a4e71ed97d18b9ad3a83850eef09a2c651e0e01 object 5fbdcc4c76301f9a1c80bdd44ba1c18c1410dc21 type commit tag v2.0 tagger zhongmingmao <[email protected] > 1492599543 +0800 tag 2.0 $ git cat-file -t 8a4e71ed97d18b9ad3a83850eef09a2c651e0e01 tag $ git cat-file -t 5fbdcc4c76301f9a1c80bdd44ba1c18c1410dc21 commit