程序人生

写优雅的程序,做优雅的人

实例探索 Git 的分支 branch 和标签 tag

| Comments

上一篇讲到 Git 的对象模型,通过它已经能够深入了解 Git 背后如何组织和储存数据,但是总觉得还是缺一点什么,那就是 Git 的必杀技分支和对象模型的关系,接下来就通过一些实例来弄清楚 Git 的分支是如何运作的。

在 Git 对象模型中讲到,每一次 Git 提交,都会生成一个 commit 对象,这个 commit 对象有一个 SHA1 key,例如 4240c635214402420f4fd907c378f0d01a5b5d8e。简单的说,Git 的分支就是一个引用 reference,这个引用有一个名称(分支的名称),然后指向一个具体的 commit 对象(通过 commit 对象的 key),就是这么简单。

分支的数据保存在那里呢?都在目录 .git/refs 中,通常这个目录下有三个子目录,分别是 heads,tags 和 remotes。 我们可以看到 .git/refs/heads 下有一些文件,每一个文件表示一个分支,文件的名称就是分支的名称,文件的内容就是 commit 对象的 key。

例如,dig-git 项目里:

1
2
3
4
cat .git/refs/heads/master
058ca0a55e60eae77dac9818f915dad581b5465b
cat .git/refs/heads/test1
0c5ca6c9e46a1e6cfe04eaea7cd5db3223ba6693

是不是很简单,知道了这个原理,我们甚至可以绕开 Git 命令,直接通过文件操作生成一个 branch。 例如:

1
echo "3c31e0a28cfc7f022984d6f8250a1c5c0670f120" >> .git/refs/heads/test2

通过上面的命令,在 .git/refs/heads 目录下生成一个 test2 文件,文件内容是一个 commit 对象的 key,这样就生成了一个 test2 分支。

标签 tag 和分支 branch 的本质是一样的,都是一个指向 commit 对象的引用,只不过标签 tag 的文件放在 .git/refs/tags 目录下而已。

Comments