Git 具有优秀的存储能力, 如果没有远端服务器,本地也能做一个版本管控的系统。为什么呢?那我们今天通过 .git目录一探究竟
执行 git init 后会在当前目录 生成一个 .git 文件夹,这里面就是 Git 最核心的东西。 进入 Git 目录可以看到类似的如下结构
├── HEAD
├── cofnig
├── refs
├── objects
HEAD 文件
$ cat .git/HEAD
打印出 ref: refs/heads/当前分支名称 , 说明HEAD 是一个引用, 指向的是当前工作分支
# 打印出: 本地所有分支, 当前分支高亮并有一个星号
$ git branch -v
# 切换到master分支
$ git checkout master
$ cat .git/HEAD
打印出 ref: refs/heads/master , 说明HEAD 是一个引用, 指向的是当前工作分支
总结: 切换分支的时候, HEAD 的内容会发生变化,以便告诉我们,现在我们工作在哪个分支上
config 文件
存放与本地仓库相关的配置信息
$ cat .git/config
打印出 当前仓库的配置信息
通过 git config 验证一下是否会影响config文件的内容
$ git config --local user.name 'guyue'
$ git config --local --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
......
......
# 打印出 user.name=guyue 表示配置已生效
user.name=guyue
# 查看config文件中的变更
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
......
......
[branch "master"]
remote = origin
merge = refs/heads/master
[remote "upstream"]
......
......
[user]
# ------------------可以看到用户名这里已经被修改了
name = guyue
[branch "patch-1"]
remote = origin
merge = refs/heads/patch-1
refs 文件夹
$ cd .git/refs
$ ls
# 打印出
heads remotes tags
出现了 heads,tags, remotes
tags 文件夹
tags 意味着我们的 git 仓库可以有很多标签,标签也叫里程碑: 项目开发到一定程度,有一个关键的成果,比如 v1.0.0 版本, 我们就可以针对 v1.0.0 版本打上标签。 标识 v1.0.0 是一个里程碑
# 在git仓库根目录创建新标签
$ git tag -a v1.4 -m "my version 1.4"
# 查看是否创建成功, 如果成功,则会打印出 v1.4
$ git tag
# ---------------------------- 练习开始
# 进入 .git/refs/tags 目录
$ cd .git/refs/tags
# 列出所有文件夹及文件, 这里会打印出 v1.4
$ ls
# 查看v1.4的内容 ,这里会出现一串哈希值(代表v1.4的版本号)
$ cat v1.4
60fbe5e04909252140c5c6c7bdc2581949828303
# 查看哈希值的类型 打印出: tag(意思是此版本号表示一个标签)
# git cat-file -t 从头截取的一段哈希值
$ git cat-file -t 60fbe5e049092
heads 文件夹
heads 对应的就是我们的分支, 分支说白了就是一个独立的开发空间,
# 进入 .git/refs/heads 目录
$ cd .git/refs/heads
$ ls
# 会打印出当前git仓库的所有本地分支名称
总结: **heads 文件夹存储了 当前 git 项目的所有本地分支 。 **
**这里可以得出 ** HEAD文件 是指针, 指向了 refs/heads/当前的工作分支
master 文件
$ cat master
# 打印出一串哈希值(不同git项目生成结果不同),
#打印出的结果是: 0b1a98929cce8eea918c160571a046586f1b033f
# 任意复制一部分编码,执行以下操作
# 查看哈希值的类型
$ git cat-file -t 0b1a98929cce
打印出 commit(表示一个提交记录)
# 查看 文件内容
$ git cat-file -p 0b1a98929cce
# ----------------------------------打印出此提交记录的内容
tree 614f56d82cde7939c1f7c1443cbece9ebc20a730
parent be7ec654102a478e812f23728542fbca72ae164c
author hh <guyue@jjjj.local> 1607502637 +0800
committer hh <guyue@jjjj.local> 1607502637 +0800
fix:修改不部分翻译
$ git branch -v
# 打印出 所有本地分支
* master 0b1a989 fix:修改不部分翻译
patch-1 b054a05 feat:ts高级类型清单
patch-2 ac6ed3a fix:合并冲突
patch-3 ac6ed3a fix:合并冲突
patch-4 ac6ed3a fix:合并冲突
patch-5 ac6ed3a fix:合并冲突
可以看到 master 指向 0b1a98929cce 这个提交记录, 因此 cat .git/refs/heads/master 指向的就是 某一次提交记录
cat .git/refs/heads/分支名称 同理
objects 文件夹
objects:存放对象 .git/objects/ 文件夹中的子文件夹都是以哈希值的前两位字符命名 每个 object 由 40 位字符组成,前两位字符用来当文件夹,后 38 位做文件。
$ cd .git/objects
$ ls
# 打印出下面的内容(不同git项目生成结果不同)
00 18 30 48 60 78 90 a8 c0 d8 f0
01 19 31 49 61 79 91 a9 c1 d9 f1
02 1a 32 4a 62 7a 92 aa c2
17 2f 47 5f 77 8f a7 bf d7 ef
可以看出, 有 info 文件夹, pack 文件夹, 两个字符组成的 N 个文件夹
练习一(blob 类型)
$ cd 00
$ ls
# 打印出下面的内容(不同git项目生成结果不同)
09659e7fbbc537bd66f76affd2e6cfb402fefb a68a4f51e4071d9d9b50144e541d44edfc989c
23c5cdf5f2fd4254a11282c52fc1fd18f012ca c85e5bfdf7308c1cc847f310a8a75c2d836ed5
4e7d16f5f24da35881e74435c0bdadd7d9dc75 cdf1634db1d9385ddb795e8814cd286cac43f6
539ec1d022549bb14aa82070ec603c6ee2595b d44d5e1a271159dbe74bf60b4dd20e96bd36d6
61102f1e521d98247143e95c15c111475e349a ee505947418c3aec9dc19a43ca772d12cfe57e
74ae975a3d60843dc8a5d12eb8f78aadb1cabe
复制 00 与 上面任意一组记录 组成一个 哈希值
# 打印出 类型是 commit 不同git项目生成结果不同
$ git cat-file -t 0009659e7fbbc537bd66f76affd2e6cfb402fefb
# 打印出下面的内容(不同git项目生成结果不同)
blob
** blob(表示是一个文件) **
打印出此文件记录的内容
$ git cat-file -p 0009659e7fbbc537bd66f76affd2e6cfb402fefb
# 可以打印出文件内容
练习二(commit 类型)
$ cd 3f
$ ls
# 打印出下面的内容(不同git项目生成结果不同)
09f7f770e2143b0a37c63339ea39bbc88a5b53 9a0fbdc8c98620f9bd38eb844635b2639a6e81
0d5f55d2ad3d788c1cb5f0811f15a1a94fc6ee c7d74438891bccc4c99d0e4dff4343b97d5e7e
4f7e532ca16ad824440fdea11cf68b62ccd3b2 dcede941d04071581e0b4f345303289eac2af0
52e346f618f8916ec49a15ffbfbd206b7e93fa f97336bbf2b943066c0497076d1731a3149fa7
72dff29a69612c14eaec559e2a11bcced48b5b
复制 3f 与 上面任意一组记录 组成一个 哈希值
$ git cat-file -t 3f0d5f55d2ad3d788c1cb5f0811f15a1a94fc6ee
#
commit
commit(表示一个提交记录)
打印出此文件的内容
$ git cat-file -p 3f0d5f55d2ad3d788c1cb5f0811f15a1a94fc6ee
# 会打印出 提交时的备注
练习三(tree 类型)
$ cd c2
$ ls
# 打印出下面的内容(不同git项目生成结果不同)
47b377ff5b1a2a6887724d3dc749a5555e5d18 8dd7896fb70a34308fac24e95ccef07e24f033
4cef38c2e64d9829e28cd94b5eef3c3a5776d3 be61fdc05dbacbe86bbd8739b273a3f48f4991
568048633b334dadfee8fd8a7f3c145432a2e6 c66fae969215048844e3720ac0aa62e6e58980
59a7f470d5e4fd82e2b62ca10e9dd32f7f96db fc78f870f6854c145881ea4ae78d5e5f9c80e8
复制 c2 与 上面任意一组记录 组成一个 哈希值
$ git cat-file -t c2e81a1619c262ac1da37410eb2d100e0105d3db
#
tree
打印出 ** tree(表示一棵树) **
打印出此树的内容
$ git cat-file -p c2e81a1619c262ac1da37410eb2d100e0105d3db
总结
在 Git 中可以通过 哈希值取得所有的东西
Git 的几种对象
- commit
- blob
- tree
跟文件查看的相关 Git 命令
# 查看文件类型
$ git cat-file -t 哈希值
# 查看文件内容
$ git cat-file -p 哈希值
# 查看文件大小
$ git cat-file -s 哈希值
.git 目录总结
HEAD文件:指向当前的工作路径config文件:存放本地仓库(local)相关的配置信息。
• refs [文件夹]
• heads (存放当前项目的所有分支)
• tags (存放的当前项目的所有标签,又叫做里程碑)
objects:存放对象 .git/objects/ 文件夹中的子文件夹都是以哈希值的前两位字符命名 每个 object 由 40 位字符组成,前两位字符用来当文件夹,后 38 位做文件。description(仓库的描述信息文件)