git的分支比较的灵活,如果使用分支的时候没有很好的计划,会使得分支太多,在合并的时候出现各种问题,所以必须在团队中对分支的管理有合理的规划和设计,Vincent Driessen的一篇文章A successful Git branching model为我们确定了分支的合理管理方式,这种方式已经成为了git默认的分支管理方式,所以git-flow也是按照这个方式来进行的,这一讲我们先把这种分支管理方式讲清楚,下一讲使用SourceTree工具来实现基于git-flow的管理。
我们的分支一般需要分为如下几个
- master
- develop
- feature/xx
- release-0.1.x
- hotfix-v0.1.x
master分支是主分支,这个分支基本不做任何的开发,仅仅只是用来确定发布版本,develop分支就是针对开发进行管理的分支,所有的新功能的开发都基于这个分支进行,当确定一个新功能之后就创建一个feature分支来处理,个人比较习惯使用feature/功能名称来创建分支,当这个功能开发完成并且测试通过之后将该功能合并到develop分支中,当这个版本完成之后,创建一个release分支说明版本信息和修复一些bug之后,在master上合并这个分支,并且打一个tag标签。接下来我们新建一个文件夹来模拟这个分支管理模型。
进入目录执行下列命令
git init
echo A successful Git branching model > readme.md
git add .
git commit -m "init"
git checkout -b develop
以上操作完成了git工厂的创建,并且提交了第一个init的版本,创建了develop的分支。现在我们有了一个新的功能,我们需要在develop的基础上建立一个新的分支来解决。
git checkout -b feature/base develop
将来所有的新功能都要创建一个feature/功能名称的分支来进行开发,在实际的项目开发中,我们通常会创建一个基础的版本,之后团队的人员在这个基础上开发自己的功能。当开发完成这个版本之后,将这个分支合并到develop分支中,并且删除这个分支。这里需要强调一下合并分支我们尽可能的使用--no-ff
参数(可以考虑将这个参数加入的到git的alias中)。
E:\teacher\git_teacher\08>git branch
* develop
master
E:\teacher\git_teacher\08>git checkout -b feature/base #创建一个新分支feature/base来设置基本信息
Switched to a new branch 'feature/base'
E:\teacher\git_teacher\08>echo base >base.txt #添加一些文件内容
E:\teacher\git_teacher\08>git add .
E:\teacher\git_teacher\08>git commit -m "finish base" #完成第一个版本的提交
[feature/base 93df1fa] finish base
1 file changed, 1 insertion(+)
create mode 100644 base.txt
E:\teacher\git_teacher\08>git checkout develop #切换回develop分支
Switched to branch 'develop'
E:\teacher\git_teacher\08>git branch
* develop
feature/base
master
E:\teacher\git_teacher\08>git merge --no-ff feature/base #合并分支
Merge made by the 'recursive' strategy.
base.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 base.txt
E:\teacher\git_teacher\08>git branch -d feature/base #删除feature分支
Deleted branch feature/base (was 93df1fa).
E:\teacher\git_teacher\08>git lg #查看日志,如果没有这个lg这个命令,请查看上一讲
* c00ee0a - (HEAD -> develop) Merge branch 'feature/base' into develop (24 seconds ago)
|\
| * 93df1fa - finish base (6 minutes ago)
|/
* 1703640 - (master) init (30 minutes ago)
这里我们完成了第一个版本的操作,这个版本是其他所有版本开发的基础,此时我们就可以创建一个release分支,将其合并到master分支中,release分支我们同样也是在develop分支上创建,为什么要创建这个release分支呢?这个分支主要是在发布前再次修复一些bug或者加入一些说明该release版本的主要功能和作用。
E:\teacher\git_teacher\08>git checkout -b release-0.0.1 develop
Switched to a new branch 'release-0.0.1'
E:\teacher\git_teacher\08>git branch
develop
master
* release-0.0.1
此时这个分支会持续一段时间来进行测试,当测试完成之后,将这个分支合并到master和develop分支上,并且在master分支上打一个标签,说明这个版本的意义,方便以后有问题的时候快速回滚。
E:\teacher\git_teacher\08>mkdir rc #创建一个文件夹来说明不同版本的更新信息
E:\teacher\git_teacher\08>echo "finish base fun" > rc/0.0.1 #根据版本的名称创建文件来说明版本信息
E:\teacher\git_teacher\08>git add .
E:\teacher\git_teacher\08>git commit -m "release 0.0.1" #提交这次release版本
[release-0.0.1 e9c7ab3] release 0.0.1
1 file changed, 1 insertion(+)
create mode 100644 rc/0.0.1
E:\teacher\git_teacher\08>git checkout master #切换回master分支
Switched to branch 'master'
E:\teacher\git_teacher\08>git merge --no-ff release-0.0.1 #在master分支上合并release-0.0.1分支
Merge made by the 'recursive' strategy.
base.txt | 1 +
rc/0.0.1 | 1 +
2 files changed, 2 insertions(+)
create mode 100644 base.txt
create mode 100644 rc/0.0.1
E:\teacher\git_teacher\08>git tag -a 0.0.1 #为该版本添加一个tag标签,说明版本的作用
以上操作完成了一个release版本的发布。之后我们还要将release-0.0.1分支合并到develop上,合并完成之后该release分支就没有实际的存在价值了,就可以直接删除该分支。
E:\teacher\git_teacher\08>git checkout develop
Switched to branch 'develop'
E:\teacher\git_teacher\08>git merge --no-ff release-0.0.1
Merge made by the 'recursive' strategy.
rc/0.0.1 | 1 +
1 file changed, 1 insertion(+)
create mode 100644 rc/0.0.1
E:\teacher\git_teacher\08>git branch -d release-0.0.1
Deleted branch release-0.0.1 (was e9c7ab3).
通过上述操作之后,我们的第一个版本就成功发布了,之后就可以由团队的开发人员在这个基础上完成各自不同的功能开发,同理每一个新的功能都要在develop分支的基础上创建feature/xx功能分支来开发。此时如果在开发的过程中发现base这个版本中的代码有问题我们该怎么办呢?我们就需要通过创建hotfix-x.x.x分支来解决这个问题,hotfix分支都是在master基础上创建的并且都是基于tag的版本号来进行的,主要用来修复用于生产环境的分支。
E:\teacher\git_teacher\08>git checkout -b hotfix-0.0.2 master #在master的基础上创建hotfix分支
Switched to a new branch 'hotfix-0.0.2'
E:\teacher\git_teacher\08>echo "hotfix" >> base.txt
E:\teacher\git_teacher\08>git add .
E:\teacher\git_teacher\08>git commit -m "update bug in 0.0.1" #完成一次修复并且提交
[hotfix-0.0.2 9d2d416] update bug in 0.0.1
1 file changed, 1 insertion(+)
E:\teacher\git_teacher\08>git checkout master #切换到master分支
Switched to branch 'master'
E:\teacher\git_teacher\08>git merge --no-ff hotfix-0.0.2 #合并hotfix分支
Merge made by the 'recursive' strategy.
base.txt | 1 +
1 file changed, 1 insertion(+)
E:\teacher\git_teacher\08>git tag -a 0.0.2 #打一个标签0.0.2
以上操作和release分支的操作类似,合并到master并且添加一个tag,最后将其合并到develop分支中并且删除hotfix分支。
E:\teacher\git_teacher\08>git checkout develop
Switched to branch 'develop'
E:\teacher\git_teacher\08>git merge --no-ff hotfix-0.0.2
Merge made by the 'recursive' strategy.
base.txt | 1 +
1 file changed, 1 insertion(+)
E:\teacher\git_teacher\08>git branch -d hotfix-0.0.2
Deleted branch hotfix-0.0.2 (was 9d2d416).
E:\teacher\git_teacher\08>git branch
* develop
master
这就是分支在开发过程中的一种标准模式,git flow就是基于这个模式设计出了一系列的命令,我们在使用的过程中并不是一定需要按照gitflow,git有一个比较好用的可视化管理工具sourceTree也可以直接使用gitflow的命令,我们下一讲就主要介绍如何在sourceTree中使用gitflow。