参考于https://git-scm.com/book/zh/v1/Git-%E5%88%86%E6%94%AF-%E4%BD%95%E8%B0%93%E5%88%86%E6%94%AF
分支:Git 中的分支,其实本质上仅仅是个指向 commit 对象的可变指针。
Git 会使用 master 作为分支的默认名字。在若干次提交后,你其实已经有了一个指向最后一次提交对象的 master 分支,它在每次提交的时候都会自动向前移动。
我们可以使用** git branch branch-name**来创建分支,例如我们创建一个叫testing 的分支:
git branch testing
此时我们只是创建了一个新的分支,并没有切换过去,所以我们还在master分支上。那Git是如何知道我们在哪个分支上的呢?因为Git中有个专门指向分支指针的指针:HEAD。
那么我们如何切换分支呢?使用**checkout **,我们来切换到testing 分支
checkout testing
这样 HEAD 就指向了 testing 分支:
如何查看当前有多少分支呢?
可以使用:git branch
frc@frc:~/GitHub/study/GitStudy$ git branch
* master
testing
我们可以看到现在有两个分支,而master分支前有个*****号,它是告诉我们这是当前所在分支,即HEAD指向的分支,我切换到testing分支再看看
frc@frc:~/GitHub/study/GitStudy$ git checkout testing
切换到分支 'testing'
frc@frc:~/GitHub/study/GitStudy$ git branch
master
* testing
我们发现*****跑到testing前面区了,说明现在在testing分支上。
此时如果我们去.git/目录下会发现多了2个文件:
logs/refs/heads/testing
refs/heads/testing
看下logs/refs/heads/testing:
0000000000000000000000000000000000000000 ce97d3ee3e85989f86e655c81a3d4d6a17461dfa fengrongcheng <fengrongcheng2017@outlook.com> 1497510595 +0800 branch: Created from master
refs/heads/testing:
ce97d3ee3e85989f86e655c81a3d4d6a17461dfa
此时里面还有个文件发生了改变:HEAD,因为现在HEAD指向的是testing了:
ref: refs/heads/testing
原来应该是:
ref: refs/heads/master
我们现在在testing分支上添加个提交看看会怎样。
我们会看到testing分支领先master分支了,二期每次提交后HEAD都随分支向前移动。
现在切回master分支:
此时把HEAD指针移回了master分支了,同时把工作目录的内容换成了master分支所指向的快照内容。
现在如果我们在master上再添加个提交,就会变成这样:
由于 Git 中的分支实际上仅是一个包含所指对象校验和(40 个字符长度 SHA-1 字串)的文件,所以创建和销毁一个分支就变得非常廉价。说白了,新建一个分支就是向一个文件写入 41 个字节(外加一个换行符)那么简单,当然也就很快了。就是上面说道的:
refs/heads/testing:
ce97d3ee3e85989f86e655c81a3d4d6a17461dfa
这和大多数版本控制系统形成了鲜明对比,它们管理分支大多采取备份所有项目文件到特定目录的方式,所以根据项目文件数量和大小不同,可能花费的时间也会有相当大的差别,快则几秒,慢则数分钟。而 Git 的实现与项目复杂度无关,它永远可以在几毫秒的时间内完成分支的创建和切换。