pro git学习笔记 2 分支
Git 分支
几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。在很多版本控制系统中,这是个昂贵的过程,常常需要创建一个源代码目录的完整副本,对大型项目来说会花费很长时间。
有人把 Git 的分支模型称为“必杀技特性”,而正是因为它,将 Git 从版本控制系统家族里区分出来。Git 有何特别之处呢?Git 的分支可谓是难以置信的轻量级,它的新建操作几乎可以在瞬间完成,并且在不同分支间切换起来也差不多一样快。和许多其他版本控制系统不同,Git 鼓励在工作流程中频繁使用分支与合并,哪怕一天之内进行许多次都没有关系。理解分支的概念并熟练运用后,你才会意识到为什么 Git 是一个如此强大而独特的工具,并从此真正改变你的开发方式。
在 Git 中提交时,会保存一个提交(commit)对象,该对象包含一个指向暂存内容快照的指针,包含本次提交的作者等相关附属信息,包含零个或多个指向该提交对象的父对象指针:首次提交是没有直接祖先的,普通提交有一个祖先,由两个或多个分支合并产生的提交则有多个祖先。
分支的新建与合并
1. 开发某个网站。 2. 为实现某个新的需求,创建一个分支。 3. 在这个分支上开展工作。
现在,你决定要修补问题追踪系统上的 #53 问题。顺带说明下,Git 并不同任何特定的问题追踪系统打交道。这里为了说明要解决的问题,才把新建的分支取名为 iss53。要新建并切换到该分支,运行 git checkout
并加上 -b
参数:
$ git checkout -b iss53 Switched to a new branch "iss53"
这相当于执行下面这两条命令:
$ git branch iss53 $ git checkout iss53
留心你的暂存区或者工作目录里,那些还没有提交的修改,它会和你即将检出的分支产生冲突从而阻止 Git 为你切换分支。
切换分支的时候最好保持一个清洁的工作区域。稍后会介绍几个绕过这种问题的办法(分别叫做 stashing 和 commit amending)。目前已经提交了所有的修改,所以接下来可以正常转换到 master
分支:
Git 会把工作目录的内容恢复为检出某分支时它所指向的那个提交对象的快照。它会自动添加、删除和修改文件以确保目录的内容和你当时提交时完全一样。
接下来,你得进行紧急修补。我们创建一个紧急修补分支 hotfix
来开展工作,直到搞定
有必要作些测试,确保修补是成功的,然后回到 master
分支并把它合并进来,然后发布到生产服务器。用 git merge
命令来进行合并:
请注意,合并时出现了“Fast forward”的提示。由于当前 master
分支所在的提交对象是要并入的 hotfix
分支的直接上游,Git 只需把 master
分支指针直接右移。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)。
现在最新的修改已经在当前 master
分支所指向的提交对象中了,可以部署到生产服务器上去了(见图 3-14)。
在那个超级重要的修补发布以后,你想要回到被打扰之前的工作。由于当前 hotfix
分支和 master
都指向相同的提交对象,所以 hotfix
已经完成了历史使命,可以删掉了。使用 git branch
的 -d
选项执行删除操作:
命令不仅仅能创建和删除分支,如果不加任何参数,它会给出当前所有分支的清单:
git branch
注意看 master
分支前的 *
字符:它表示当前所在的分支。也就是说,如果现在提交更新,master
分支将随着开发进度前移。若要查看各个分支最后一个提交对象的信息,运行 git branch -v
:
用 git branch --merge
查看哪些分支已被并入当前分支(译注:也就是说哪些分支是当前分支的直接上游。)
之前我们已经合并了 iss53
,所以在这里会看到它。一般来说,列表中没有 *
的分支通常都可以用 git branch -d
来删掉。原因很简单,既然已经把它们所包含的工作整合到了其他分支,删掉也不会损失什么。
另外可以用 git branch --no-merged
查看尚未合并的工作:
它会显示还未合并进来的分支。由于这些分支中还包含着尚未合并进来的工作成果,所以简单地用 git branch -d
删除该分支会提示错误,因为那样做会丢失数据:
$ git branch -d testing error: The branch 'testing' is not an ancestor of your current HEAD. If you are sure you want to delete it, run 'git branch -D testing'.
不过,如果你确实想要删除该分支上的改动,可以用大写的删除选项 -D
强制执行,就像上面提示信息中给出的那样。
由于 Git 使用简单的三方合并,所以就算在较长一段时间内,反复多次把某个分支合并到另一分支,也不是什么难事。也就是说,你可以同时拥有多个开放的分支,每个分支用于完成特定的任务,随着开发的推进,你可以随时把某个特性分支的成果并到其他分支中。
现在我们来看一个实际的例子。请看图 3-20,由下往上,起先我们在 master
工作到 C1,然后开始一个新分支 iss91
尝试修复 91 号缺陷,提交到 C6 的时候,又冒出一个解决该问题的新办法,于是从之前 C4 的地方又分出一个分支 iss91v2
,干到 C8 的时候,又回到主干 master
中提交了 C9 和 C10,再回到 iss91v2
继续工作,提交 C11,接着,又冒出个不太确定的想法,从 master
的最新提交 C10 处开了个新的分支dumbidea
做些试验。