第5章 分支工作流


现在你已经学会了分支的基本操作。本章节将学习分支工作流。


5.1 典型的分支模型

第5章 分支工作流​_git



maseter:主分支只存放最稳定的代码,通常是一个软件的发行版(release)。

develop:开发分支,并不要求一直稳定,但当开发分支比较稳定的时候,就可以合并到主分支。

topic:主题分支,又叫特性分支,是为了开发某一个功能或者特性而做的分支(比如登录功能、注册功能等等),在特性开发完毕并测试成功之后,就合并到开发分支。并且被合并之后通常会删除掉。


注意,越下层的分支越不稳定,提交的次数越多;越上层的分支越稳定,提交的次数越少--仅仅在下层分支稳定的时候才将下层分支合并到上层分支。很多公司按照这个套路发展出了更多层的分支。



5.2 主题分支

主题分支在任何规模的项目中都非常有用。主题分支就是为了开发某一个功能或者某一个特性而临时存在的分支,当功能开发完毕且通过测试后,主题分支会被合并到上层分支中,然后主题分支就会被删除掉。这样的操作对于其他的VCS软件而言是十分奢侈的,但是在Git中,却是鼓励程序员大量地使用分支!


让我们来看一个例子:

第5章 分支工作流​_远程分支_02


你从master分支创建了另一个分支以完成一个功能:iss91, 而在 iss91 分支开发的过程中,你又另一个想法,于是你在iss91分支上有创建了一个分支:iss91v2以用另一种想法开发同一个功能,然后你又切换回master分支继续做了一些master分支上的开发,开发到某个节点时,你发现你接下来要开发的功能所用的方法你不确定是否是一个好办法,所以你有创建了一个分支:dumbidea分支,并在该分支上继续实现你的想法,此时你的提交历史看起来就是上面的样子。


假设你更喜欢 iss91v2 分支的解决方案,并且你把你的dumbidea分支给你的团队成员都看了看,并且大伙一直认为dumbidea分支的代码简直是惊为天人!于是你合并了 iss91v2 到 master 分支中,并强制删除了 iss91 分支(也就是舍弃了C5和C6提交),然后也将 dumbidea 合并到了 master 分支中,你的提交历史看起来是这个样子:

第5章 分支工作流​_远程仓库_03



注意,以上的操作都是操作本地的分支。当你新建和合并分支的时候,所有这一切都只发生在你本地的 Git 版本库中 —— 此时并没有涉及到远程服务器中的分支。



5.3 远程分支

通过以下命令,可以查看远程仓库的信息

git remote show origin


在使用远程仓库时,“远程跟踪分支”是一个很常用的技术。首先不要被远程跟踪分支这个名字迷惑了,远程跟踪分支并不存在于远程仓库,它只存在于本地仓库中。另外因为任何分支都是指针,所以远程跟踪分支也是一个指针,但是你并不能移动这个指针。你应该把远程跟踪分支当做一个“书签”

这个“书签”记录了你最后一次与一个远程分支连接时,那个远程分支所处于的提交。


远程跟踪分支的名字的形式为:<remote>/<branch>。比如如果你想看看你本地的master分支对应的远程仓库中的master,在你上次连接它的时候,处于哪一次的提交,你应该查看origin/master这个远程跟踪分支。又比如你和另外一个小伙伴共同协作开发 iss53 分支,此时在你的本地仓库中有一个名字 iss53 的分支,同时本地的 origin/iss53 这个远程跟踪分支代表了上一次你与远程仓库中的 iss53 分支连接的状态。


这听起来有点混乱,让我们来看一个例子。假设你有一个git远程仓库,如果你从该远程仓库克隆到本地仓库,则在该本地仓库中git会自动命名该远程仓库为 origin ,并且拉取该仓库中的所有数据,并且在本地仓库中创建一个远程跟踪分支:origin/master以跟踪远程仓库中master分支的状态,git同时也会为你创建一个与远程分支完全一致的本地分支master:

第5章 分支工作流​_git_04


注意以上的origin/master分支是一个远程跟踪分支,它存在于本地仓库中,真正的远程分支master 是处在远程仓库中的!且 origin/master 是一个只读的分支,你无法直接移动它,除非你再次与远程分支连接上,才会更新 origin/master 分支。


你可以通过以下命令看到远程跟踪分支

git branch -a


如果你在本地分支master上做了一些提交,与此同时,其他人推送了一些新的提交到远程仓库的master分支中,此时本地仓库和远程仓库的提交历史看起来是这个样子:

第5章 分支工作流​_git_05


只要你的本地master分支一直不与远程仓库中的master分支连接,则你本地的 origin/master 远程跟踪分支就会一直处在那个固定的位置。


为了与远程仓库中的master分支保持同步,你可以运行以下命令:

git fetch <remote>


git pull = git fetch + git merge



在本例子中,就是运行

第5章 分支工作流​_远程分支_06



这种情况下,你可以使用 git merge 来让 master 分支合并 origin/master 分支,虽然我们不能直接移动 origin/master 分支,但是却可以合并它。实际上我们之前使用的git pull就是git fetch和 git merge的结合。



Pushing Branch

当你想公开一个你本地的某一个分支时,只需要将该分支推送到一个你拥有写权限的远程仓库上。同样,如果你本地有一些你不想公开的私有分支,你也可以藏着玩,然后把私有分支合并到公开的分支上再推送也行。


如果你有一个名叫serverfix的分支,你想把该分支公开以便与其他小伙伴在其上协作开发,你可以键入以下命令:

git push origin serverfix


此后在其他小伙伴执行

$ git fetch origin


注意以上命令并不会在本地仓库生成serverfix分支,而仅仅只生成了orgin/serverfix这个远程跟踪分支。此时对于这个远程跟踪分支origin/serverfix,你有两种处理方式,一种是将其合并到其他分支上,另一种是根据origin/serverfix这个远程跟踪分支直接生成本地分支serverfix,命令如下:

git checkout -b serverfix origin/serverfix


此后你就可以在本地的 serverfix 分支上进行开发工作了。


你可以使用以下命令查看本地仓库中的分支与远程仓库中的分支的对应关系

git branch -vv


你可以使用以下命令来让一个本地分支与一个远程分支发生“追踪”关系

$ git checkout -b 本地分支名 远程追踪分支



5.4 注意

如果你在你的个人分支上,删除了A.java,虽然将你的个人分支合并到了dev分支,然后再将dev分支push到远程,那么这个删除A.java的动作会一起push上去(千万不要以为A.java不存在了,所以对A.java的操作就不会push到远程dev分支了,因为git管理的是动作而非文件)。此时别的小伙伴将dev pull下来,那么小伙伴本地的A.java就会被删除!