目录
分支是什么?
创建分支
切换分支
补充
俗话说得好 —— 该来的总是会来的!
之前我们一直把分支挂在嘴边,吊足了大家的胃口,这一节开始我就来给大家讲讲 Git 的分支和分支管理!分支无疑是 Git 最值得傲娇的技能,不信你看它的 LOGO :
这不就是个大写的劈叉嘛~
假设你的大项目已经上线了(有上百万人在使用呢),过了一段时间你突然觉得应该添加一些新的功能,但是为了保险起见,你肯定不能在当前项目上直接进行开发,这时候你就有另(创)起(建)炉(分)灶(支)的需要了。
放个大图先让你知道分支大概是咋回事:
如果没有分支,整个产品的迭代周期就会因为新功能的开发而被延误(因为还有补 bug 这样比较着急的任务)……可见分支对于版本控制系统来说是多么重要!
不过话说回来,目前几乎所有的版本控制系统都以某种形式支持分支,那么 Git 还有什么好嘚瑟的呢?
记得在第一讲介绍 Git 的时候跟大家分享过资深玩家对 SVN 的吐槽:
克隆一份全新的目录以同样拥有 5 个分支来说,SVN 是同时复製 5 个版本的文件,也就是说重复 5 次同样的动作。而 Git 只是获取文件的每个版本的元素,然后只载入主要的分支(master)在我的经验,克隆一个拥有将近一万个提交(commit),5 个分支,每个分支有大约 1500 个文件的 SVN,耗了将近 1 小时!而 Git 只用了区区的 1 分钟!
“克隆一个拥有将近一万个提交(commit),5 个分支,每个分支有大约 1500 个文件的 SVN,耗了将近 1 小时!而 Git 只用了区区的 1 分钟!”……突然我想起了一句话 —— 天下武功,唯快不破!
我们深入一点思考,到底是什么成就了 Git“秒男”的称号呢?
在 Git实用教程 2.0:Git 理论基础 中,我们介绍理论的时候,说 Git 采用一种看似“异端”的形式来处理版本迭代 —— 通常的版本控制系统是采用增量文件系统(增量文件系统的意思就是说新的快照存放的是与旧的快照不同的那一部分内容)来管理版本迭代;而 Git 则是采用将每个版本都独立存储的方式 —— 看上去使用 Git 会耗费更多的空间,但来到分支管理这一块,却成了 Git 完胜其它版本控制系统的关键!
因为对于其它版本控制系统而言,创建分支常常需要完全创建一个源代码目录的副本,项目越大,耗费的时间就越多;而 Git 由于每一个结点都已经是一个完整的项目,所以只需要创建多一个“指针”(像 master)指向分支开始的位置即可。
下边我给大家演示如何创建和切换分支,我们来到之前的 MyProject2(如果你已经删了,没关系,重新创建一个项目,然后随便写点东西,提交然后修改,再提交,即可):
MyProject2 现在仓库里的情况如下:
创建分支,使用 git branch 分支名 命令:
没有任何提示说明分支创建成功(一般也不会失败啦,除非创建了同名的分支会提醒你一下),
此时可以执行 git log --decorate 命令查看:
decorate 这个选项是让 log 显示指向这个提交的所有引用(比如 分支以及后面会讲的标签)
大家会看到 原来的 (HEAD -> master)变成了 (HEAD -> master,feature)
它的意思是:目前有两个分支,一个是主分支(master),一个是刚才我们创建的新分支(feature),然后 HEAD 指针仍然指向默认的 master 分支。
所以目前仓库中的快照应该是这样:
创建分支我们会了,接下来就是切换分支。
现在我们需要将工作环境从默认的 master 分支切换到新创建的分支(feature)上,使用的就是之前我们欲言又止的 checkout 命令。
git checkout 分支名
执行 git checkout feature 命令:
这样 HEAD 指针就指向 feature 分支了:
什么?!口说无凭!
好吧,你们要的证据在这里:
(如果希望以“精简版”的方式显示,可以加上一个 --oneline 选项(即 git log --decorate --oneline),这样就只用一行来显示一个快照记录。)
看到没有?HEAD 指针已经指向了 feature 分支:(HEAD -> feature)
我们现在对 MyProject2 里面的文件进行修改,我们就改一下 DEADME.md 为例。
执行 git status 命令查看状态:
然后 提交到暂存区域。
可以看到 README.md 文件被修改并添加到暂存区域(还没有提交),所以当前三棵树应该是这样:
现在我们进行一次提交:(其实只要是在切换分支之后使用 commit 提交的都会归为切换后的分支上去,即使是在创建和切换分支使用了 add 添加到了暂存区域,即在那个分支提交的就属于哪个分支)
现在仓库中的快照应该是酱紫:
然后我们将 HEAD 指针切回 master 分支:
你们现在可以看一下 README.md 文件,细心的朋友会发现上一次对 README.md 文件的修改已经荡然无存了,这是因为我们的工作目录已经回到 master 分支的状态中:
并且此时我们 使用 git log 命令查看历史记录,是看不到 feature 分支的,因为从 HEAD 出发没有线指向 feature
现在对 README.md 文件进行修改(随便改改),然后执行git add 文件名 和 git commit -m "change the README file again":
好了,目前仓库中的快照应该变成了酱紫:
什么?!不相信?
好吧,让 Git 自己来告诉你!
执行 git log --decorate --oneline --graph --all 命令:
--graph 选项表示让 Git 绘制分支图,--all 表示显示所有分支
下面给大家介绍一下 Git 在实际开发中是如何进行分支管理的
Git 工作流使用一个中间仓库作为所有开发者的交流地点,开发程序的小伙伴在本地工作,然后将各自的分支推送到中间仓库。
代替单一的 master 主分支,上图的工作流使用了两个分支来处理项目发布和日常开发。
master 主分支通常只是用于对外发布项目的新版本,日常开发应该在另一条分支上完成。我们把开发用的分支叫做 develop 分支。
每一个新功能应该使用单独一个功能分支进行开发,功能分支应该从开发分支中分离出来,功能开发完成后合并到开发分支。
提示1:功能分支不应该跟 master 分支有任何交流。
提示2:功能分支可以采用 feature-* 的形式命名。
在项目正式发布之前,你可能需要一个预发布的版本进行测试。于是你可以从开发分支中分离出预发布分支,用于内部或公开的测试。
提示1:预发布分支应该同时合并到主分支和开发分支中。
提示2:预发布分支可以采用 release-* 的形式命名。
项目正式发布后难免会出现 bug,这时就需要创建一个分支,进行 bug 的修补。
提示1:维护分支应该从主分支中分离出来,bug 被修补后,再合并到主分支和开发分支中。
提示2:维护分支可以采用 fixbug-* 的形式命名。
常设分支就主分支(master)和开发分支(develop)两个即可,另外的功能分支(feature)、预发布分支(release)和维护分支(hotfix)属于临时分支,用完之后应该及时删除。