前言
本篇主要介绍了 git 初始化后的 .git 目录,虽然平时我们不用去关注,但是了解一下git的存储原理还是可以的;
目录
- git 初始化
- objects 目录
- refs 目录
- HEAD 文件
正文
1. git初始化
这里的初始化有两种方式;
-
方式1:
git init
,直接在对应的目录执行git init命令,此时会在当前目录生成一个.git目录D:\StudyData\github-project\GitLearning\GitBasic>git init Initialized empty Git repository in D:/StudyData/github-project/GitLearning/GitBasic/.git/
-
方式2:
git clone
,将远程仓库的项目克隆到本地,这种方式的前提是 项目已经存在于git仓库中D:\StudyData\github-project\GitLearning\GitBasic>git clone git@github.com:Jalon2015/git-basic-demo.git Cloning into 'git-basic-demo'... warning: You appear to have cloned an empty repository.
-
因为这里的远程仓库的项目是空的(刚在GitHub创建的),所以会有一个空项目的提示;
-
这里克隆的项目会单独创建一个子目录,存放到当前目录(这一点跟git init不同,git init会直接在当前目录初始化)
-
不管是哪种方式,都会在对应目录生成一个.git目录,内容如下所示:
-
hooks
: 存放钩子脚本,在我们执行git命令时会触发这里的钩子脚本 -
info
: 初始化后,默认info内部会生成一个exclude文件,用来记录要排除的文件的忽略模式(即不希望被提交的文件通配符)exclude类似于.gitignore,不同的是exclude文件只存在本地,仅自己可见;而.gitignore会被提交,所有人可见
-
objects
: 核心目录之一,存放了git仓库的所有数据(下面有详细介绍) -
refs
: 核心目录之一,存放了分支branch、标签tags、远程仓库等数据的指针(下面有详细介绍) -
config
: 配置文件,记录了该项目的git相关配置(这里的git配置会覆盖全局git配置) -
description
: 描述文件,这个文件的作用就是描述该项目的相关信息;- 该文件的默认内容为
Unnamed repository; edit this file 'description' to name the repository.
; - 该文件不需要我们操作,仅供GitWeb(GitHub的一个前身)使用
- 该文件的默认内容为
-
HEAD
:该文件指向当前操作的分支当前操作的分支,可通过
git branch
查看
2. objects 目录
上面简单介绍了.git目录的组成,下面我们就详细介绍下.git目录的核心组成
先从 objects目录开始;
objects 目录存放了git的所有数据内容,我们可以把它当作一个数据库(类似于redis键值对形式);
每次我们执行git add
和git commit
命令时,本质就是把数据保存到objects目录;
刚初始化后的objects目录有两个目录,info和pack,且都为空;
- 现在我们新建一个a.txt,并执行
git add
进行提交:
touch a.txt
git add a.txt
- 此时再查看objects目录,会发现多了一个目录e6,如下所示,这里多出来的/e6/9de29...文件就是刚才我们添加的a.txt,只不过换了一种形式进行保存
$ ls -R
.:
e6/ info/ pack/
./e6:
9de29bb2d1d6434b8b29ae775ad8c2e48c5391
./info:
./pack:
- 接着执行
git commit -m "add a.txt",会发现objects下又多了两个目录
,这里多出来的就是提交的数据
这里需要注意一点,我们每执行一次git add或者git commit,就会在objects目录下添加新的目录,而不是覆盖已有的目录,这正是版本控制的强大之处:保存历史记录,进行细粒度的版本管理,方便追溯
3. refs 目录
该目录记录的是分支的引用信息,也就是分支指向的是哪条commit记录;
这里的分支默认为master主分支,后面创建了其他分支会自动添加进来
下面我们用例子来看下:
- 先查看提交的历史记录
$ git log
commit 72c17db1e70b1399a35ae64c114112ae890d98e4 (HEAD -> master)
Author: jalon2015 <1121263265@qq.com>
Date: Wed Jan 19 15:56:10 2022 +0800
update a.txt 2
commit 5e1e2692fd45c6c04b80279d89b6b6c632c2cfc4
Author: jalon2015 <1121263265@qq.com>
Date: Wed Jan 19 15:27:49 2022 +0800
update a.txt
commit fdbd487e4167174a4b987dc1f2ce7377a15337c4
Author: jalon2015 <1121263265@qq.com>
Date: Wed Jan 19 15:19:29 2022 +0800
add a.txt
可以看到,最新的提交记录为 72c17
- 再查看.git/refs/heads/master文件,可以看到,指向的就是最新提交
$ cat .git/refs/heads/master
72c17db1e70b1399a35ae64c114112ae890d98e4
-
此时我们再创建并切换分支dev
$ git branch dev # 创建分支dev $ git branch # 查看当前的所有分支 dev * master $ git switch dev # 切换到dev分支 Switched to branch 'dev'
再次查看refs/heads目录,可以看到多了一个dev文件,这个dev文件存储的就是我们刚才创建的dev分支的引用信息;
现在我们可以查看下dev文件的内容,如下所示:可以看到,内容就是最新的commit记录
$ cat .git/refs/heads/dev 72c17db1e70b1399a35ae64c114112ae890d98e4
4. HEAD 文件
这个就比较清晰了,就是存储当前指向的分支;
而分支具体引用的是哪个commit记录,就要去上面的refs中查找了;
-
我们先看下当前的HEAD文件内容:
$ cat .git/HEAD ref: refs/heads/dev
可以看到,当前指向的是dev分支
-
当我们切换到master分支时,再查看下:
$ git switch master Switched to branch 'master' $ cat .git/HEAD ref: refs/heads/master
可以看到,现在指向的是master分支
总结
.git目录就是git的核心数据存储区,包括所有的数据存储、引用对象、各个分支等信息。
评论区