JHHK

欢迎来到我的个人网站
行者常至 为者常成

4、Git基础(三)

目录

探秘.git目录

一、.git目录

我们在工程目录下可以看到有一个隐藏目录 .git
进入.git 目录

localhost:firstProject LC$ cd .git
localhost:.git LC$ ls -al
total 48
drwxr-xr-x  13 LC  staff  416  1 11 17:45 .
drwxr-xr-x   7 LC  staff  224 12 22 16:12 ..
-rw-r--r--   1 LC  staff   20 12 22 16:10 COMMIT_EDITMSG
-rw-r--r--   1 LC  staff   20  1 11 17:40 HEAD
-rw-r--r--   1 LC  staff  175 12 22 16:26 config
-rw-r--r--   1 LC  staff   73 12 22 11:29 description
-rw-r--r--   1 LC  staff  129 12 25 13:42 gitk.cache
drwxr-xr-x  14 LC  staff  448 12 22 11:29 hooks
-rw-r--r--   1 LC  staff  482  1 11 17:40 index
drwxr-xr-x   3 LC  staff   96 12 22 11:29 info
drwxr-xr-x   4 LC  staff  128 12 22 14:01 logs
drwxr-xr-x  15 LC  staff  480 12 22 16:10 objects
drwxr-xr-x   4 LC  staff  128 12 22 11:29 refs

二、HEAD

-rw-r--r--   1 LC  staff   20  1 11 17:40 HEAD
#可以看出这是一个文件,看下文件内容
localhost:.git LC$ cat HEAD 
ref: refs/heads/dev

#文件内容指向了refs/heads/dev文件

#查看下分支
localhost:.git LC$ git branch -av
* dev    666fb34 modified index.html
  master 666fb34 modified index.html

#可以看出HEAD内的引用指向的路径是与当前分支有一定联系的      
#指向的是当前工作分支    
#我们再来验证下
localhost:firstProject LC$ git checkout master
Switched to branch 'master'
localhost:firstProject LC$ cat .git/HEAD 
ref: refs/heads/master

如果我们手动将HEAD文件的内容改为ref:refs/heads/dev,我们当前的分支就变为了dev

三、config

-rw-r--r--   1 LC  staff  175 12 22 16:26 config
#可以看出这是一个文件,看下文件内容
localhost:.git LC$ cat config 
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	ignorecase = true
	precomposeunicode = true
[user]
	name = LC
	email = LC@163.com
localhost:.git LC$ 

#可以看出,这个文件是当前仓库的配置信息。与下面指令显示的内容相同    
git config --local --list

当我们手动修改config的文件内容时,当前仓库的配置信息也就更改了

四、refs

localhost:.git LC$ cd refs/
localhost:refs LC$ ls -al
total 0
drwxr-xr-x   4 LC  staff  128 12 22 11:29 .
drwxr-xr-x  13 LC  staff  416  1 11 21:55 ..
drwxr-xr-x   4 LC  staff  128 12 25 13:49 heads   #heads:分支 
drwxr-xr-x   2 LC  staff   64 12 22 11:29 tags    #tags:标签或者里程碑   
localhost:refs LC$ 

我们进入到heads里边看下

localhost:refs LC$ cd heads/
localhost:heads LC$ ls -la
total 16
drwxr-xr-x  4 LC  staff  128 12 25 13:49 .
drwxr-xr-x  4 LC  staff  128 12 22 11:29 ..
-rw-r--r--@ 1 LC  staff   41 12 25 13:49 dev
-rw-r--r--  1 LC  staff   41 12 22 16:10 master
localhost:heads LC$ cat dev
666fb34b3499cb2937178fc246432e5bfaef6f43
localhost:heads LC$ cat master
666fb34b3499cb2937178fc246432e5bfaef6f43
localhost:heads LC$ 
localhost:heads LC$ git cat-file -t 666fb34b3499c #查看下类型
commit

我们进入到tags里边看下

localhost:refs LC$ cd tags
localhost:tags LC$ ls -al
total 8
drwxr-xr-x  3 LC  staff   96  1 11 22:09 .
drwxr-xr-x  4 LC  staff  128 12 22 11:29 ..
-rw-r--r--  1 LC  staff   41  1 11 22:09 js01
localhost:tags LC$ cat js01
6c76e0433c0bcd24106e8888dfc963c42a2cfaff
localhost:tags LC$ git ca-file -t 6c76e043
tag
localhost:tags LC$ 

#在看下这个tag里边有什么

localhost:tags LC$ git ca-file -p 6c76e043
object 666fb34b3499cb2937178fc246432e5bfaef6f43
type commit
tag js01
tagger LC <LC@163.com> 1610374172 +0800

localhost:tags LC$ 

#这个tag指向一个对象,这个对象的类型是一次提交

五、objects

localhost:.git LC$ cd objects/
localhost:objects LC$ ls -la
total 0
drwxr-xr-x  16 LC  staff  512  1 11 22:09 .
drwxr-xr-x  14 LC  staff  448  1 11 22:18 ..
drwxr-xr-x   3 LC  staff   96 12 22 16:09 12
drwxr-xr-x   3 LC  staff   96 12 22 16:10 66
drwxr-xr-x   3 LC  staff   96 12 22 13:46 6a
drwxr-xr-x   3 LC  staff   96  1 11 22:09 6c
drwxr-xr-x   3 LC  staff   96 12 22 16:10 87
drwxr-xr-x   3 LC  staff   96 12 22 14:01 96
drwxr-xr-x   3 LC  staff   96 12 22 15:31 ab
drwxr-xr-x   3 LC  staff   96 12 22 16:10 ae
drwxr-xr-x   3 LC  staff   96 12 22 13:51 da
drwxr-xr-x   3 LC  staff   96 12 22 14:01 de
drwxr-xr-x   3 LC  staff   96 12 22 15:31 ef
drwxr-xr-x   4 LC  staff  128 12 22 16:10 f4
drwxr-xr-x   2 LC  staff   64 12 22 11:29 info
drwxr-xr-x   2 LC  staff   64 12 22 11:29 pack    #pack 是将松散的文件整合在一起
localhost:objects LC$ 

我们先进入一个目录看下

localhost:objects LC$ cd ae
localhost:ae LC$ ls -la
total 8
drwxr-xr-x   3 LC  staff   96 12 22 16:10 .
drwxr-xr-x  16 LC  staff  512  1 11 22:09 ..
-r--r--r--   1 LC  staff   53 12 22 16:10 e37060401d19e7bd9f80b7b33920a000e96b5b

#ae 与 e37060401d19e7bd9f80b7b33920a000e96b5b拼接
localhost:ae LC$ git cat-file -t aee37060401d19e7bd9f80b7b33920a000e96b5b     
tree
localhost:ae LC$ 

看下这个tree的内容

localhost:ae LC$ git cat-file -p aee37060401d19e7bd9f80b7b33920a000e96b5b
100644 blob ef3f137d8af338a8604544a3e482090684321d93	style.css
localhost:ae LC$ 

我们看到有一个blob,这也是一种类型,代表文件

localhost:ae LC$ git cat-file -t ef3f137d8af3
blob

看下blob文件的内容

localhost:ae LC$ git cat-file -p ef3f137d8af3
body{
  background-color: orange;
  font-family: 'Monaco', sans-serif;
  color: white;
}

body a{
  color: white;
}
...

objects文件夹内放置的都是对象:commit,tree,blob
比如我们某次提交的哈希值是:159a7af383ffa1e672967210ca7ce9fc0eb89082
那么objects文件夹下就会有一个15命名的文件夹,文件夹内就会有一个9a7af383ffa1e672967210ca7ce9fc0eb89082文件
通过 文件夹名 + 文件夹内文件名 我们就可以得到一个完整的哈希值,通过这个哈希值我们就可以访问到这个对象,这个对象可能是commit,tree,blob

对象

一、commit对象

#我们cd到refs/heads目录下看下分支
#选择一个分支,看下它当前的指向,并看下指向的是什么类型
localhost:heads LC$ cat dev
666fb34b3499cb2937178fc246432e5bfaef6f43
localhost:heads LC$ git cat-file -t 666fb34b3
commit


#我们看下commit对象的内容是什么
localhost:heads LC$ git cat-file -p 666fb34b3
tree f41484d33118e7663f4cda47d4f2cea130b3dede
parent dee94861245b0ea5119d1c19e6939cfa381e5bf0
author LC <LC@163.com> 1608624623 +0800
committer LC <LC@163.com> 1608624623 +0800

modified index.html
localhost:heads LC$ 

可以看到commit对象内容包含了:
tree、
parent、
author、
committer、
提交内容

从commit对象的结构看,commit包含了一个tree对象

二、tree对象

我们在看下tree对象都包含什么内容

localhost:heads LC$ git cat-file -t f41484d33118
tree
localhost:heads LC$ git cat-file -p f41484d33118
040000 tree 96b67e399c8496ec36cbbbcb776eb924fad7f9a7	images
100644 blob 12146421dc47fd303d9547279c746508f969b92a	index.html
040000 tree 87b3e92f70e7dfa555f141afeae28a2bc4a343b6	js
040000 tree aee37060401d19e7bd9f80b7b33920a000e96b5b	styles
localhost:heads LC$ 

我们看到这个tree对象内容包含了:
tree、
blob、
tree、
tree

从tree的结构看,tree包含了嵌套的tree对象和blob对象

三、blob对象

localhost:heads LC$ git cat-file -t 12146421dc47fd3
blob
localhost:heads LC$ git cat-file -p 12146421dc47fd3
<!DOCTYPE html>
<html>
<head>
    <title>Git Demo</title>
    <link rel="stylesheet" type="text/css" href="styles/style.css">
</head>

blob对象指向的是文件

四、三个对象的关系

img

一次提交对应一个commit对象A
commit对象A下有一个tree对象B
tree对象B下面可以包含blob对象或tree对象
blob对象指向的是文件,tree对象指向的是文件夹

一次commit是对当时文件的一个快照

数一数tree的个数

新建的Git仓库,有且仅有1个commit,仅仅包含 /doc/readme ,请问内含多少个tree,多少个blob?

localhost:watch_git_objects LC$ find .git/objects/ -type f
.git/objects//10/e150673e2e38b3c923872eb5d94984f6625aed
.git/objects//08/3e18d286d8d2a9eda8c62d9d98935dcc07ca4c
.git/objects//ba/8711bd7540faa22e4e76a1cf5c78501fa4e162
.git/objects//2d/832d9044c698081e59c322d5a2a459da546469

我们发现objects目录下有4个对象,我们来看下都是什么对象

localhost:watch_git_objects LC$ git cat-file -t 10e150673e2
commit
localhost:watch_git_objects LC$ git cat-file -p 10e150673e2s
tree 083e18d286d8d2a9eda8c62d9d98935dcc07ca4c
author LC <LC@lakala.com> 1610420977 +0800
committer LC <LC@lakala.com> 1610420977 +0800

Add readme
localhost:watch_git_objects LC$ git cat-file -p 083e18d28
040000 tree ba8711bd7540faa22e4e76a1cf5c78501fa4e162	doc
localhost:watch_git_objects LC$ git cat-file -p ba8711bd7
100644 blob 2d832d9044c698081e59c322d5a2a459da546469	readme
localhost:watch_git_objects LC$ git cat-file -p 2d832d904
hello,world
localhost:watch_git_objects LC$ 

我们可以看出有一个commit对象,两个tree对象,一个blob对象,并且其关系如下图:

img

实践

创建两个不同的 Git 仓库,在⾥⾯添加相同内容的⽂件,然后把 它们都加⼊到暂存区中,再看看两个仓库中同内容的⽂件对应的 blob 的 hash 值是否相同?多试⼏次看看结论是否⼀样?

我们创建三个仓库demo1,demo2,demo3,并将文件index.html添加到仓库暂存区

localhost:demo3 LC$ cd ..
localhost:gitDemo LC$ find demo1/.git/objects/ -type f
demo1/.git/objects//6a/d4c68d567a1a5b415dcfce2010fce1a60b245f
localhost:gitDemo LC$ find demo2/.git/objects/ -type f
demo2/.git/objects//6a/d4c68d567a1a5b415dcfce2010fce1a60b245f
localhost:gitDemo LC$ find demo3/.git/objects/ -type f
demo3/.git/objects//6a/d4c68d567a1a5b415dcfce2010fce1a60b245f
localhost:gitDemo LC$ 

可以看出三个仓库内对象的hash值都是一样的,说明git只看文件内容,而不关心文件名及其它信息


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.