一个文件来保存 SHA-1 值,而该文件有一个简单的名字, 然后用这个名字指针来替代原始的 SHA-1 值,在 Git 中,这种简单的名字被称为“引用(references,或简写为 refs)”。
你可以在 .git/refs 目录下找到这类含有 SHA-1 值的文件。
$ find .git/refs
.git/refs
.git/refs/heads
.git/refs/tags
创建一个引用
$ echo 2fc8b03017c7ef6b756b1118cf65929335f62a25 > .git/refs/headers/master
$ git log --pretty=oneline master
2fc8b03017c7ef6b756b1118cf65929335f62a25 (HEAD -> master) third commit
926561854dc207207d7e9d9618bde0536a3c5a6e second commit
345d3bae6f29b7af6aa0b200858d9061f1180da4 first commit
Git 不提倡直接编辑引用文件,git 提供了一个更加安全的命令。
git update-ref refs/headers/master 2fc8b03017c7ef6b756b1118cf65929335f62a25
这基本就是 Git 分支的本质:一个指向某一系列提交之首的指针或引用。
HEAD 引用
HEAD 文件通常是一个符号引用(symbolic reference),指向目前所在的分支。 所谓符号引用,表示它是一个指向其他引用的指针。
然而在某些罕见的情况下,HEAD 文件可能会包含一个 git 对象的 SHA-1 值。 当你在检出一个标签、提交或远程分支,让你的仓库变成 “分离 HEAD”状态时,就会出现这种情况。
直接查看 HEAD 文件内容
$ cat .git/HEAD
ref: refs/heads/master
git 命令查看(更安全
$ git symbolic-ref HEAD
ref: refs/heads/master
git 命令设置(更安全
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
ref: refs/heads/test
注意不要设置为不符合引用规范的值
标签引用
标签对象(tag object) 非常类似于一个提交对象——它包含一个标签创建者信息、一个日期、一段注释信息,以及一个指针。 主要的区别在于,标签对象通常指向一个提交对象,而不是一个树对象。 它像是一个永不移动的分支引用——永远指向同一个提交对象,只不过给这个提交对象加上一个更友好的名字罢了。
创建一个轻量标签:
$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d
若要创建一个附注标签,Git 会创建一个标签对象,并记录一个引用来指向该标签对象,而不是直接指向提交对象。
$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'test tag'
$ cat .git/refs/tags/v1.1
9585191f37f7b0fb9444f35a9bf50de191beadc2
$ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
object 1a410efbd13591db07496601ebc7a059dd55cfe9
type commit
tag v1.1
tagger Scott Chacon Sat May 23 16:48:58 2009 -0700
test tag
标签对象并非必须指向某个提交对象;你可以对任意类型的 Git 对象打标签。 例如,在 Git 源码中,项目维护者将他们的 GPG 公钥添加为一个数据对象,然后对这个对象打了一个标签。
远程引用
远程引用和分支(位于 refs/heads 目录下的引用)之间最主要的区别在于,远程引用是只读的。 虽然可以 git checkout 到某个远程引用,但是 Git 并不会将 HEAD 引用指向该远程引用。因此,你永远不能通过 commit 命令来更新远程引用。 Git 将这些远程引用作为记录远程服务器上各分支最后已知位置状态的书签来管理。
$ cat .git/refs/remotes/origin/master
ca82a6dff817ec66f44342007202690a93763949