什么是分支
简单来说,分支就是一个独立于原开发主线的一个源代码副本,这样就能在修改源程序时无需影响源程序。而修改源程序是在副本上修改,之后与主分支进行合并。但显然这样的效率并不是太高,特别是大型项目,这样的过程特别耗费时间。
这时候Git的优势就显现了,有人吧Git 的分支模型称为它的“必杀技特性”,也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。要知道Git分支能脱颖而出,就要先明白Git的实现原理。
Git的实现原理
在Git的官方文档中对于Git的文件保存有这样一句话“ Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照 。”,也就是说Git仅仅保存某个时间点,项目里的文件都是什么样的,像一张照片一样。一张照片就代表一个版本,在不同版本切换也就是寻找那个时刻的照片。
而这一切的实现的得益于指针的使用,在我们git commit
的时候,Git会保存一个提交对象(commit object),里面就包含了指向暂存的那张照片的指针,当然对象中还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象(即当前对象的前身,可能是空,也可能是两个快照的合并)的指针。
这里我们借用Git官方手册的例子(文章尾有链接)来说明
在我们使用git add
提交暂存时,Git会计算每个文件的校验和(使用SHA-1 哈希算法),然后会把文件快照保存在Git仓库中(使用blob对象来保存,如下图的右边三个对象)。
然后,当我们执行以下提交指令时
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'
Git会计算每个子目录的校验和,然后把这些校验和保存为一个树对象,里面包括除暂存对象包含的信息外,还包含指向这个树对象(项目根目录)的指针。至此,Git就能重现这个时间点项目快照。
由此可见,一次提交后,Git仓库中有以上5个对象,三个 blob 对象(黄色,保存着文件快照)、一个 树 对象 (蓝色,记录着目录结构和 blob 对象索引)以及一个 提交 对象(白色,包含着指向前述树对象的指针和所有提交信息)。
当我们多次提交后,提交对象间就会指向上一个提交对象(如下图)
Git分支的本质
明白了Git的实现原理,对于Git分支,其实就是就是指向提交对象的一个指针,我们平时所见的master分支仅仅是因为我们一般使用git init
来初始化仓库,所以默认生成的分支都叫master,但其实master并没有什么特别,更其他后面创建的分支一样的。
分支的创建
使用如下命令即可创建一个名为testing的分支,实际上就是一个新的可移动指针。
$ git branch testing
这时可以看到两个分支指向了同一个提交对象,那Git是怎么区分这时候使用的分支是哪个的呢?
在这点上,Git使用了一个名为HEAD的指针,它指向本地当前正使用的分支,由此来区分上述情况。
我们也能使用如下命令来查看各分支所指对象
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) add feature #32 - ability to add new formats to the central interface
34ac2 Fixed bug #1328 - stack overflow under certain conditions
98ca9 The initial commit of my project
分支切换
使用如下命令即可
$ git checkout testing
参考资料
Git官方文档git-scm.com/book/zh/v2/…分支-分支简介
\