目录
Git 在创建仓库的时候会在当前仓库目录下创建名为 .git 的隐藏目录,用于存储仓库配置以及数据信息。本文将结合实例对 Git 仓库的基本目录进行介绍。
一、实例环境
下文中的实例均是在如下环境中进行的:
系统环境:CentOS Linux release 7.6.1810 (Core)
git版本:git version 1.8.3.1
远程仓库:GitHub。
二、目录结构
初始化仓库使用 git init 命令,初始目录(.git)结构如下所示:
[root@192 testgit]# 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
[root@192 testgit]#
这个初始化后的仓库,当创建完分支 dev-branch,并 push 后,目录结构如下所示:
[root@192 testgit]# tree .git/
.git/
├── branches
├── COMMIT_EDITMSG
├── 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
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ ├── heads
│ │ ├── dev-branch
│ │ └── master
│ └── remotes
│ └── origin
│ └── master
├── objects
│ ├── 2d
│ │ └── d2c71b69c837a7459f4bd9c9f7db6520731d06
│ ├── 5c
│ │ └── 7b8eda18a75e13d27c31e65a54b0abd7948510
│ ├── 77
│ │ └── cad3aecf7c2754231095598119979d62a1e1da
│ ├── info
│ └── pack
└── refs
├── heads
│ ├── dev-branch
│ └── master
├── remotes
│ └── origin
│ └── master
└── tags
19 directories, 25 files
[root@192 testgit]#
接下来将会对各个目录以及文件进行详细的介绍。
2.1 branches 目录
一种不常用的存储速记方式,用于指定git fetch,git pull和git push的URL,目前已基本不用。
2.2 COMMIT_EDITMSG 文件
把大写变成小写就容易理解了,commit_editmsg :commit 编辑信息,仅记录最近一次提交的 commit 编辑信息,例如:
[root@192 testgit]# vim README
[root@192 testgit]# git add .
[root@192 testgit]# git commit -m "modify README file"
[master 2392c4d] modify README file
1 file changed, 2 insertions(+), 1 deletion(-)
[root@192 testgit]# git push origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 315 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To [email protected]:New-World-2019/testgit.git
3cbe67c..2392c4d master -> master
[root@192 testgit]# cat .git/COMMIT_EDITMSG
modify README file
[root@192 testgit]#
上述例子中,先修改了 README 文件,然后 push 到远程,在 commit 时写了 “modify README file”,之后查看 COMMIT_EDITMSG文件存储的即为提交时的备注信息。
2.3 config 文件
看名字就知道了,存储当前仓库的配置信息。git 的配置文件分为三层,分别是:
- /etc/gitconfig 文件:系统上每一个用户及他们仓库的通用配置;
- ~/.gitconfig 或 ~/.config/git/config 文件:当前用户的仓库配置;
- .git/config 文件(当前仓库下):当前用户当前仓库的配置;
最下层的优先级最高,会覆盖上层的配置信息,可以通过 git config 参数对上述文件进行修改,可配置的信息包括:用户信息、http 信息、仓库信息等。
[root@192 testgit]# cat ~/.gitconfig
[user]
name = New-World-2019
email = [email protected]
[http]
postBuffer = 1048576000
lowSpeedLimit = 0
lowSpeedTime = 999999
[root@192 testgit]# cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = [email protected]:New-World-2019/testgit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "dev-branch"]
remote = origin
merge = refs/heads/dev-branch
[root@192 testgit]# git config --list
user.name=New-World-2019
[email protected]
http.postbuffer=1048576000
http.lowspeedlimit=0
http.lowspeedtime=999999
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
[email protected]:New-World-2019/testgit.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
branch.dev-branch.remote=origin
branch.dev-branch.merge=refs/heads/dev-branch
[root@192 testgit]#
在上面例子中, 系统中没有创建 /etc/gitconfig 文件便没有打印出来。可以看出的是,在当前仓库下 git config --list 命令的结果为文件 ~/.gitconfig 和 .git/config 的和。如果需要了解更多配置信息,可以通过 git config 命令进一步了解。
2.4 description 文件
用于在 GitWeb 中展示项目的描述信息。默认内容如下:
Unnamed repository; edit this file 'description' to name the repository.
2.5 HEAD文件
存储 HEAD 指针,指向当前分支,即:记录当前活动分支,例如:
[root@localhost testgit]# git status
# 位于分支 master
无文件要提交,干净的工作区
[root@localhost testgit]# cat .git/HEAD
ref: refs/heads/master
[root@localhost testgit]# git checkout dev-branch
切换到分支 'dev-branch'
[root@localhost testgit]# cat .git/HEAD
ref: refs/heads/dev-branch
[root@localhost testgit]#
在上述例子中,开始是在 master 分支,切换到 dev-branch 分支后,文件 .git/HEAD 的内容变成了 refs/heads/dev-branch。
2.6 hooks 目录
目录下存储了许多钩子文件(一些脚本),这些文件是各种 Git 命令使用的自定义脚本,可以在Git 特定阶段自动执行,例如:提交 (commit)、变基 (rebase)、拉取 ( pull ) 操作的前后执行。运行 git init 时会安装一些示例钩子,但是默认情况下它们都被禁用。如果要启用,需要删除文件.sample后缀。
2.7 index 文件
暂存区(stage),二进制文件。
2.8 info 目录
存储库的其他信息将记录在此目录中。
info/exclude : 忽略指定模式的文件,和 .gitignore 类似,但是 .gitignore 是针对每个目录的。
2.9 logs 目录
保存所有更新的引用记录。其目录结构如下:
[root@localhost logs]# tree
.
├── HEAD
└── refs
├── heads
│ ├── dev-branch
│ └── master
└── remotes
└── origin
├── dev-branch
└── master
4 directories, 5 files
[root@localhost logs]#
其中,HEAD 记录所有更改记录,包括切换分支,logs/refs 下存储本地和远程分支的更改记录。
2.10 objects 目录
Git 是一个内容寻址文件系统,Git 的核心部分是一个简单的键值对数据库(key-value data store)。 你可以向 Git 仓库中插入任意类型的内容,它会返回一个唯一的键,通过该键可以在任意时刻再次取回该内容。
简单理解就是:objects 目录是 Git 的数据库(键值对数据库,可以想象为 map[key] = value 的形式),根据 key 来存取内容,key 即为 SHA1计算后的值。该目录下存储有三种对象(最多):数据对象(blob object)、树对象(tree object)、提交对象(commit object)。
(1)info 和 pack 目录
当存储的文件很大时,git 会进行压缩,会存储到 info 和 pack 下;
(2)2个字符命令的目录
首先,这两个字母是计算的SHA1值(总共40个字符)的前两个字符,剩余的38个是该目录下的文件名。
2.11 refs 目录
(1)heads 目录
目录有以各个本地分支名命名的文件,保存对应分支最新提交的ID,是通过SHA1算法计算的一个字符串。
(2)remotes 目录
目录有以各个远程分支名命名的文件,保存对应分支最新提交的ID,和 heads 目录一个原理。
(3)tags 目录
存储在开发过程中打的标签,里面的文件以标签名命令,文件内容为对应的ID。
三、参考文献
[1] What is Git's description file?
[2] gitignore
[3] git branches