之前介绍过,分支 master
的存在方式无非就是在目录 .git/refs/heads
下的文件(或叫引用)而已,分支保存的提交 ID
会随着提交而变化,可以使用 git checkout
命令检出分支,使用 git reset
命令重置分支指向的提交 ID
。默认会创建 master 分支,实际项目中是多分支协助开发的,对分支进行创建、切换、合并、变基分支等操作。
为什么代码管理要用到分支呢?
新版本的开发往往是和当前版本同步进行的,应避免在同一个分支中进行功能开发。即使多个成员都在为同一个项目的同一版本进行开发,但每个人接受的任务不尽相同,有的任务开发周期很长,有的任务需要对软件架构进行较大的修改,如果都在同一分支中,就会因过频的代码合并冲突导致效率低下。
成功的软件项目大多要经历多个开发周期,发布多个软件版本。而每个已经发布的版本都可能出现
bug
,这就需要对历史版本进行更改,应避免在同一个开发分支中进行 bug 修复。敏捷开发管理模式中,如果不能将项目的各个功能模块通过分支进行隔离,在软件集成上就会比较麻烦。
分支操作场景一(对已经发布的软件版本进行 Bug 修复而不引入正在开发的新功能的代码)
在该场景下创建的分支叫做 Bugfix
分支,在软件新版本发布后,经常使用此方式进行软件维护,发布升级版本。
上图演示了如何操作 Bugfix
分支进行版本迭代的过程:
F1.1
是正在开发的新功能的提交(当前为主线开发分支)。此时发现了第一个
bug
需要修复,基于上次软件发布时最后一次提交进行Bugfix
分支的创建,并进行修复提交fix1
。此分支并没有包含F1.1
的功能代码。将
Bugfix
分支向主线开发分支做一次合并,因为主线分支也同样存在该Bug
。继续开发,
F1.2
是正在开发的新功能的新提交,此时反馈发现了第二个bug
。切换到
Bugfix
分支,进行bug
修复提交fix2
,再次向主线分支进行合并。
总结:针对不同的 Bug
,都可以通过 Bugfix
分支进行修复并发布,不会因为正在开发的新功能而影响到发布的版本。如果都在同一分支处理,只能将新功能代码注释掉,进行 Bug
修复之后再发布新版本,新版本会包含被注释的新代码。如果没注释干净新功能代码或者不小心将之前修复 bug
的代码也注释了,结果将非常糟糕,新版本会出现不完整的功能或新版本重现之前处理好的 bug
。
分支操作场景二(项目开发周期延期了,砍掉一些功能,提前上线)
如果项目功能都在单一主线分支开发,功能都是同时进行的,要将一个将要完成的功能从中撤销,工作量是非常大的,还可能会牵涉到其他相关模块的变更。创建分支将某个功能或模块的开发与主线开发分支独立,是解决类似问题的办法,这种用途的分支被称为特性分支。
上图演示了如何操作特性分支的过程:
说明:圆圈代表功能一的相关提交,三角代表功能二的相关提交(假设现在有两个模块功能)
多个开发者负责的功能一和功能二的提交混杂在主线开发分支中(实际开发中,一开始就应该创建特性分支进行各自功能的开发)。
当得知功能二不在此次产品发布计划后,需要进行一个或多个反向提交(通过
git revert {commit}
命令),将功能二的相关代码全部撤销。图中用倒三角(编号为F2.X
) 表示多次反向提交最后的提交节点。在最后反转提交节点处创建一个特性分支,然后将功能二的历史提交拣选 (通过
git cherry-pick {commit}
) 到功能二特性分支上。现在功能一和功能二就互相不影响了,两边都可以继续功能的开发提交,最后只发布功能一的主线分支即可。后续功能二完成之后,再合并到主线分支,进行完整功能的版本发布。完全不用将功能二的开发停下来,如果功能一和功能二由两个不同团队来实现,难不成只上线功能一时,整个功能二的团队放长假吗?不可能的。
总结:对于一些试验性、探索性的功能开发,一些功能复杂、开发周期长(有在发布版本被取消的风险)的模块,会更改软件体系架构,破坏软件集成或者容易导致冲突,影响他人开发进度的模块,都应该为其建立特性分支。
分支操作场景三(项目要引用到第三方的代码)
有的项目要引用到第三方的代码并且需要对其进行定制,有的项目甚至整个都基于开源项目进行的定制。创建供应或叫卖主分支可以部分解决这类问题。所谓卖主分支,就是在版本库中创建一个专门和上游第三方的代码进行同步的分支,一旦上游代码发布,就检入到卖主分支中,在某个时机再将卖主分支合并到主线分支中。
上图演示了如何操作卖主分支的过程:
图中标记为
v1.0
的提交就是检入三方代码上游版本库的提交。在主线上进行定制开发,
c1
、c2
分别代表历次定制提交。当上游有了新版本发布后,假设为
v2.0
版本,就将上游新版本的源代码提交到卖主分支中。然后在主线上合并卖主分支上的新提交,合并后的提交标记为 M1 ,后续的更新发布也是同样的操作。
分支命令概述
分支管理使用命令 git branch
命令。该命令的主要用法如下:
用法1:git branch
用法2:git branch {branchname
}
用法3:git branch {branchname} {start-point}
用法4:git branch -d {branchname}
用法5:git branch -D {branchname}
用法6:git branch -m {oldbranch} {newbranch}
用法7:git branch -M {oldbranch} {newbranch}
用法8:git checkout -b {branchname}
说明:
用法 1 用于显示本地分支列表,当前分支在输出中会显示为特别的颜色,并用星号 "*" 标识出来。
用法 2 和用法 3 用于创建分支。用法 2 基于当前
HEAD
指向的提交创建分支,用法 3 基于提交start-point
创建新分支,分支名为branchname
。用法 4 和用法 5 用于删除分支。用法 4 在删除分支时会检查所要删除的分支是否已经合并到其他分支中,如果没有,则删除失败。而用法 5 会强制删除分支,即使该分支还没有合并到任何一个分支中。
用法 6 和用法 7 用于重命名分支,如果版本库中已经存在名为
newbranch
的分支,用法 6 会操作失败,而用法 7 会强制执行。用法 8 会创建分支并且自动切换到当前创建的分支上。