复习一下
之前我们学习过git的基本概念:
-
工作区: 就是我们安装在电脑上,能清晰的看到的目录。目录中能看到具体的文件内容,可以进行编辑、删除等等操作。
-
暂存区: 暂存区,英文就是stage或者index。存在工作区目录下".git"下的index文件中
-
版本库: 工作区目录下".git"目录不属于工作区,而是Git的版本库
本文主要探秘.git目录
这里从创建一个仓库开始,从零探索.git目录。
环境win10 git version 2.23.0.windows.1
1. 创建仓库
创建一个空目录,并进行git init初始化仓库。
2. .git目录解读
能看到所有目录文件 config文件 、description文件、 HEAD文件、 hooks目录 、info目录 、 objects目录 、refs目录 、logs目录、index文件
-
index文件
存放暂存区信息
-
logs目录
记录提交信息
-
hooks目录
存放一些脚本文件, Git 提供了一套脚本,可以在每个有意义的 Git 阶段自动运行。这些被称为钩子的脚本可以在提交 (commit)、变基 (rebase)、拉取 ( pull ) 操作的前后运行。脚本命预示着它的执行时机。如我们可以编写 pre-push 的作为钩子,进行推送代码前的检查
-
info目录
你可以将不想被 git 管理的文件记录到 .gitignore 文件中。排除文件(info目录下有一个exclude文件)的意思是不想共享这个文件。例如你不想共享你的 IDE 自定义配置,将其添加到 .gitignore 文件中即可
-
description文件
git仓库的描述信息,没怎么用到,查资料说是git web用到
-
config文件
此文件是本地仓库的配置文件,关于本地仓库的设置,都存储在这里。我们可以编辑这个文件或者使用git命令添加本地仓库设置。
比如:设置本地用户名密码
$ cat config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[user]
name = marsha
$ vim config
$ git config --local --list
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
user.name=genggai
- objects目录
回顾一下之前学习的Git概念:
Git通过元数据存储文件,Git内容存储通过哈希算法(SHA-1),这样可以确保内容的完整性。这是Git存储的核心功能,了解这一块非常有必要的
所以我们每一次提交commit,都会生成一个commit对象。通过git log
命令可以查看commitId
为了方便讲解,我在本地仓库创建了一些文件和目录。然后将这些更改作为一次提交。commit到本地仓库
这时候再去看objects目录,就很有意思了,会生成很多目录以及文件。这里就不截图。感兴趣的可以自行尝试一下。把目录名字和文件名字拼起来,就是一个Git object。
Git object 的对象类型: commit、tree 、blob
这三者究竟是什么关系呢?我觉得上图比较容易讲解。这个图,就用我刚才提交的内容。
另外介绍一个命令 git cat-file -p/-t object_id
查看git对象的内容(-p)或者类型(-t)
通过上述命令:汇总出一下结果
如图所示:
每一个commit对象中包含tree(目录)、parent(父commit_id)因为我是第一次提交,所以没有、作者author、提交者commiter以及提交信息
每一个tree对象可包含tree对象和blob对象(就是具体的超文本信息就是文本文件、图片、视频、音频等等)
- HEAD文件
git 中的所有内容都可以通过正确的哈希值来获取到。HEAD理解为指向你正在使用的分支(也不一定是分支,可以是标签,commit_id)的顶端的指针,而这个文件就是记录的HEAD所指向的位置
一般我们是指向那个分支,就说明我们当前处于哪个分支下做开发。当然如果有一天,git checkout到一个commitid下了,那么就会处于一个分离头指针(HEAD指向的不是分支,继续开发产生的commit有可能会被git清楚,因此做了变更之后,可以生成分支进行保存)的状态。这个状态有好有坏。看你具体的需求,是有意的还是不小心切换的。
分支其实也是指针,会指向我们具体开发的commit_id。这个commit_id随着我们不断地开发,分支所指向地commit_id也会发生变化。
tag标签, 叫做里程碑。是我们开发到一定程度,做的一次发布。他指向一个具体的commit_id。并且不会发生改变。如图所示:每一个圆圈代表一次commit
其实也可以通过gitk
命令或者git log --graph
查看具体的提交网络图理解
-
ref目录
引用,refs下有三个文件夹。
- heads 里面包含所有的本地分支,每个分支都是文件,文件中存储了分支当前指向的commit
打开refs\heads\master文件查看,可以看到其中保存的确实是最近一次提交的commit - tags 叫做里程碑,或者版本发布用等记录重要版本。
- remotes,远程仓库信息
- heads 里面包含所有的本地分支,每个分支都是文件,文件中存储了分支当前指向的commit
总结:
我们本次探秘.git目录的目的就是旨在学习以及了解git优秀的存储能力。并且认识git的对象之间的关系,以及HEAD还有分支,标签之间的关系。帮助我们更好的理解git