在《Git原理-元数据之谜》中,我们简单介绍了一下两个引用文件:HEAD
、refs/heads/main
。本文我们详细介绍一下在git中,有哪些引用文件以及这些文件都是用来做什么的。
HEAD
- 文件:
.git/HEAD
- 当前仓库的头指针,它可能是一个sym-ref(里面存储了一个字符串,指向另外一个引用文件),或者是一个OID(object-id),指向一个commit对象
- 当用户执行
git checkout <SHA1>
时,会将HEAD中的内容设置为一个commit对象的OID,一般情况下时指向一个分支的sym-ref;
1
2
3
4
5
6
7
8
|
## 指向一个分支
cat .git/HEAD
ref: refs/heads/master
## 指向一个特定的commit
git checkout 2ddde35
cat .git/HEAD
2ddde356826d4ce2c3f5fffd44c5093d7f1221aa
|
## 指向一个分支
cat .git/HEAD
ref: refs/heads/master
## 指向一个特定的commit
git checkout 2ddde35
cat .git/HEAD
2ddde356826d4ce2c3f5fffd44c5093d7f1221aa
branch
- 文件位于:
.git/refs/heads/
- 这是我们最常见的一个引用,记录当前开发的主分支信息
- 里面存放的是一个commit对象的OID
- 当我们在这个分支下执行
git commit
操作时,会将里面的内容修改为最新的commit对象的OID
- 位于
.git/refs/heads
目录下的文件分别对应了一个本地分支,可以被独立创建和删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
## master分支引用
cat .git/refs/heads/master
b69cab5ee8f71009d312611ab87263a8b588abd8
## 修改master分支引用
git commit -m "new commit for master"
cat .git/refs/heads/master
15fd76b46eecca06277b06d992ca7da67e5e7411
## 新建分支引用dev
git checkout -b dev
cat .git/refs/heads/dev
b69cab5ee8f71009d312611ab87263a8b588abd8
## 删除dev分支引用
git branch -D dev
ls .git/refs/heads
master
|
## master分支引用
cat .git/refs/heads/master
b69cab5ee8f71009d312611ab87263a8b588abd8
## 修改master分支引用
git commit -m "new commit for master"
cat .git/refs/heads/master
15fd76b46eecca06277b06d992ca7da67e5e7411
## 新建分支引用dev
git checkout -b dev
cat .git/refs/heads/dev
b69cab5ee8f71009d312611ab87263a8b588abd8
## 删除dev分支引用
git branch -D dev
ls .git/refs/heads
master
remotes
- 文件位于:
.git/refs/remotes/<remote-name>/
- 记录了远端引用的相关信息,里面包含了两个文件:
- HEAD是一个符号引用,指向远端master分支引用;
- master指向一个远端的commit对象OID
- 可以使用
git remote add/remove
来新建和删除远端引用
- 可以使用
git fetch
和git push
来更新远端引用的信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
## 检查远端引用origin相关信息
cat .git/refs/remotes/origin/HEAD
ref: refs/remotes/origin/master
cat .git/refs/remotes/origin/master
15fd76b46eecca06277b06d992ca7da67e5e7411
## 添加一个新的远端引用
git remote add github git@github.com:ticktechman/demo.git
git remote -v
github git@github.com:ticktechman/demo.git (fetch)
github git@github.com:ticktechman/demo.git (push)
origin /Users/ticktech/usr/playground/git/demo.git (fetch)
origin /Users/ticktech/usr/playground/git/demo.git (push)
git push github
|
## 检查远端引用origin相关信息
cat .git/refs/remotes/origin/HEAD
ref: refs/remotes/origin/master
cat .git/refs/remotes/origin/master
15fd76b46eecca06277b06d992ca7da67e5e7411
## 添加一个新的远端引用
git remote add github git@github.com:ticktechman/demo.git
git remote -v
github git@github.com:ticktechman/demo.git (fetch)
github git@github.com:ticktechman/demo.git (push)
origin /Users/ticktech/usr/playground/git/demo.git (fetch)
origin /Users/ticktech/usr/playground/git/demo.git (push)
git push github
- 文件位于:
.git/refs/tags/
- 有两类tags引用:普通的、带注释的
- 可以使用
git tag <tag-name>
创建普通tag,使用git tag <tag-name> -m "xxx"
创建带注释信息的tag
- tag的内容不可被修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
## 查看tag信息
git tag -l
v0.1
v0.2
## 创建普通tag
git tag v0.1 HEAD
## 普通tag指向一个commit对象
cat .git/refs/tags/v0.1
1484b845a4740af06ccbe7d19901dbcca86a248c
git cat-file -p 1484b845a4740af06ccbe7d19901dbcca86a248c
tree 032b962a1b664a74363fa46fc908e744324e27f0
parent 2ddde356826d4ce2c3f5fffd44c5093d7f1221aa
author wystan <oswystan@126.com> 1717808388 +0800
committer wystan <oswystan@126.com> 1717808388 +0800
1
## 创建带注释信息的tag
git tag v0.2 -m "v0.2 released"
## 带注释信息的tag指向一个tag对象,这个tag对象指向一个commit对象
cat .git/refs/tags/v0.2
715e4b0a6221d2449b314e68790098cea5e62905
git cat-file -p 715e4b0a6221d2449b314e68790098cea5e62905
object b69cab5ee8f71009d312611ab87263a8b588abd8
type commit
tag v0.2
tagger wystan <oswystan@126.com> 1717808752 +0800
v0.2 released
|
## 查看tag信息
git tag -l
v0.1
v0.2
## 创建普通tag
git tag v0.1 HEAD
## 普通tag指向一个commit对象
cat .git/refs/tags/v0.1
1484b845a4740af06ccbe7d19901dbcca86a248c
git cat-file -p 1484b845a4740af06ccbe7d19901dbcca86a248c
tree 032b962a1b664a74363fa46fc908e744324e27f0
parent 2ddde356826d4ce2c3f5fffd44c5093d7f1221aa
author wystan <oswystan@126.com> 1717808388 +0800
committer wystan <oswystan@126.com> 1717808388 +0800
1
## 创建带注释信息的tag
git tag v0.2 -m "v0.2 released"
## 带注释信息的tag指向一个tag对象,这个tag对象指向一个commit对象
cat .git/refs/tags/v0.2
715e4b0a6221d2449b314e68790098cea5e62905
git cat-file -p 715e4b0a6221d2449b314e68790098cea5e62905
object b69cab5ee8f71009d312611ab87263a8b588abd8
type commit
tag v0.2
tagger wystan <oswystan@126.com> 1717808752 +0800
v0.2 released
stash
- 文件:
.git/refs/stash
- 这是在执行
git stash
操作时创建的文件,里面对应的是一个commit对象的OID;
- 这里新创建了一个commit,用于记录本次stash操作的信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
## 修改一个文件,然后执行下面的stash命令
git stash
## 查看stash中的内容
cat .git/refs/stash
063c84a00c12ca4de380b0a6c8be233e643fdb48
## 查看这个OID对应的commit对象的内容
git cat-file -p 063c84a00c12ca4de380b0a6c8be233e643fdb48
tree b8ab1cbcac9442078c111eea5c2f7d4e2b7f3565
parent 15fd76b46eecca06277b06d992ca7da67e5e7411
parent 352352a403f70885e8905d64f228196bd5a89b2b
author wystan <oswystan@126.com> 1717812687 +0800
committer wystan <oswystan@126.com> 1717812687 +0800
WIP on master: 15fd76b new commit for master
|
## 修改一个文件,然后执行下面的stash命令
git stash
## 查看stash中的内容
cat .git/refs/stash
063c84a00c12ca4de380b0a6c8be233e643fdb48
## 查看这个OID对应的commit对象的内容
git cat-file -p 063c84a00c12ca4de380b0a6c8be233e643fdb48
tree b8ab1cbcac9442078c111eea5c2f7d4e2b7f3565
parent 15fd76b46eecca06277b06d992ca7da67e5e7411
parent 352352a403f70885e8905d64f228196bd5a89b2b
author wystan <oswystan@126.com> 1717812687 +0800
committer wystan <oswystan@126.com> 1717812687 +0800
WIP on master: 15fd76b new commit for master
注意上面的commit信息中,有两个parent,其中一个是在执行stash命令前,当前分支的commit对象OID,另一个是一个新建的commit对象,和第一个parent指向的tree对象为同一个,也就是说指向了同一个版本快照。关系图如下:
packed-refs
- 文件:
.git/packed-refs
- 包含所有引用,每个引用占用一行
- git在使用过程中,优先使用
.git/refs/xxx
目录下的引用,如果找不到,则到packed-refs
中查找
1
2
3
4
5
6
7
8
9
|
## 文件内容
cat .git/packed-refs
15fd76b46eecca06277b06d992ca7da67e5e7411 refs/heads/master
15fd76b46eecca06277b06d992ca7da67e5e7411 refs/remotes/github/master
15fd76b46eecca06277b06d992ca7da67e5e7411 refs/remotes/origin/master
f5a0fc64531839b87fb2b2d6154eca3b5c7f64ae refs/stash
1484b845a4740af06ccbe7d19901dbcca86a248c refs/tags/v0.1
715e4b0a6221d2449b314e68790098cea5e62905 refs/tags/v0.2
^b69cab5ee8f71009d312611ab87263a8b588abd8
|
## 文件内容
cat .git/packed-refs
15fd76b46eecca06277b06d992ca7da67e5e7411 refs/heads/master
15fd76b46eecca06277b06d992ca7da67e5e7411 refs/remotes/github/master
15fd76b46eecca06277b06d992ca7da67e5e7411 refs/remotes/origin/master
f5a0fc64531839b87fb2b2d6154eca3b5c7f64ae refs/stash
1484b845a4740af06ccbe7d19901dbcca86a248c refs/tags/v0.1
715e4b0a6221d2449b314e68790098cea5e62905 refs/tags/v0.2
^b69cab5ee8f71009d312611ab87263a8b588abd8
others
当然还有一些其他的引用,只是平时用得不多,包括:
.git/refs/replace/
.git/refs/notes/commit
.git/refs/prefetch/
.git/refs/rewritten/