在熟悉git的基本操作后,其实应该引入更加专业的工具让Git规范起来。在上周学习git flow 和git cz(规范commit)的使用,确实用起来了可以减少很多麻烦。本文旨在介绍最近学习的Git flow流程和如何使用工具践行这个流程。
关于git flow的详细介绍,本文参考了该文章(可能国内访问有问题):
https://nvie.com/posts/a-successful-git-branching-model/
git flow 是一种使用git 的流程,比较规范和易于管理。将在第一节介绍git flow流程及手动实现。当然也有相应的工具(在第二节中介绍)来简化flow流程的涉及到的较为繁琐命令。
一副用于标识git flow流程的图经常出现在关于git 规范化使用文中,这里也贴一下:
从上图就可以很容易地看几种git flow常用的分支,这几种分支也同时说明git flow流程,
Git flow 将分支主要分为两类:
1主要分支(main branches)
2支持分支(Supporting branches)
1 origin/master是主要分支,其中HEAD的源代码总是反映生产就绪状态。
2 origin/develop是主要分支,其中HEAD的源代码始终反映了下一版本中最新交付的开发更改的状态。
当develop分支中的源代码达到稳定点并准备好发布时,所有更改都应以某种方式合并回master ,然后使用版本号进行标记。
功能分支(feature)
发布分支(realease)
修复分支(fix)
这些分支中的每一个都有特定的目的,并且必须遵守关于哪些分支可以是它们的起始分支以及哪些分支必须是它们的合并目标的严格规则
所以主要分支master/develop的作用是非常清晰明了的,我们规范使用的应该是那些功能分支。
功能分支(或有时称为主题分支)用于为即将发布或将来的版本开发新功能。 在开始开发特征时,此特征将在其中合并的目标版本可能在此时未知。 功能分支的本质是,只要该功能处于开发阶段,它就会存在,但最终会合并回develop (以便将新功能添加到即将发布的版本中)或丢弃(在实验令人失望的情况下)。功能分支通常仅存在于开发人员存储库中,而不是origin 。
完整使用的feature分支的git code :
$ git checkout -b myfeature develop
Switched to a new branch "myfeature"
$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557 # merge 回去feature中commit中的记录
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop
发分支是从develop分支创建的。 例如,假设版本1.1.5是当前的生产版本,我们即将推出一个大版本。 develop状态已经为“下一个版本”做好了准备,我们已经决定这将成为版本1.2(而不是1.1.6或2.0)。 因此,我们创建分支并为release分支提供反映新版本号的名称
$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)
在创建新分支并切换到它后,我们会修改版本号。 这里, bump-version.sh是一个虚构的shell脚本,它可以更改工作副本中的某些文件以反映新版本。 (这当然可以是手动更改 - 关键是某些文件会发生变化。)然后,提交了有问题的版本号。
这个新的分支可能存在一段时间,直到发布可能肯定推出。 在此期间,可以在此分支中应用错误修复(而不是在develop分支上)。 严禁在此处添加大型新功能。 它们最终必须合并回develop ,因此,等待下一个大的发布
当发布分支的状态准备好成为真正的发布时,需要执行一些操作。 首先,release分支合并为master (因为master上的每个提交都是定义的新版本,请记住)。 接下来,必须标记master上的提交,以便将来参考此历史版本。 最后,在发布分支上进行的更改需要合并回到develop ,以便将来的版本也包含这些错误修复。
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2
为了保持发布分支中所做的更改,我们需要将这些更改合并到develop,比如一些存在的bug修复 。
$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
这一步很可能导致合并冲突(可能甚至,因为我们已经更改了版本号)。 如果是这样,请修复并提交。
现在我们已经完成了,并且可能会删除发布分支,因为我们不再需要它了:
$ git branch -d release-1.2
修补程序分支非常类似于发布分支,因为它们也是为了准备新的生产版本,尽管是计划外的。 它们源于必须立即采取实际生产版本的不良状态。 当必须立即解决生产版本中的关键错误时,可以从标记生产版本的主分支上的相应标记分支修补程序分支。实质是团队成员(在develop部门)的工作可以继续,而另一个人正在准备快速生产修复。
从master分支创建修补程序分支。 例如,假设版本1.2是当前生产版本正在运行并且由于严重错误而导致麻烦。 但是develop变化还不稳定。 然后我们可以分支修补程序分支并开始修复问题:
$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)
分支后升级版本号!//脚本更新程序中的版本号
然后,修复错误并在一个或多个单独的提交中提交修复。
$ git commit -m "Fixed severe production problem"
完成后,bugfix需要合并回master ,但也需要合并回develop ,以保证bugfix也包含在下一个版本中。 这与发布分支的完成方式完全相似。
首先,更新master并标记发布。
$ git checkout master
切换到分支'主'
$ git merge --no-ff hotfix-1.2.1
通过递归合并。
(变更摘要)
$ git tag -a 1.2.1
接下来,在develop包含bug修复:
$ git checkout develop
切换到分支'发展'
$ git merge --no-ff hotfix-1.2.1
此处规则的一个例外是, 当发布分支存在时,需要将修补程序更改合并到该发布分支中,而不是develop 。 在发布分支完成时,将错误修复反向合并到发布分支中最终将导致错误修复合并到develop 。 (如果立即develop工作需要这个错误修复,并且不能等待发布分支完成,您可以安全地将错误修复合并到develop 。)
最后,删除临时分支:
$ git branch -d hotfix-1.2.1
在第一节中,介绍了master/develop分支的主要作用及相关功能性分支,这里就浓重介绍下引入git flow工具来简化上诉流程。
我们可以先找个目录 敲下git flow的命令,找不到命令即需要安装。(好像git bash 自带)
ubuntu:
apt-get install git-flow
安装后,我们到工程所在的目录初始化该工程
(前提:我们需要确保该工程的git是已经提交,没有保存更改)
git flow init
接着git flow会弹出提示让你确定或填入 1中介绍的哪些分支
No branches exist yet. Base branches must be created now.
Branch name for production releases: [master]
Branch name for "next release" development: [develop]
How to name your supporting branch prefixes?
Feature branches? [feature/]
Bugfix branches? [bugfix/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
Hooks and filters directory? [/home/ubuntu/study/.git/hooks]
上面代码确定git flow流程中的分支名,这里全程默认,一路回车。
填完后,我们git flow工具就有以下分支
Master
develop
feature 新功能分支
bugfix bug修复分支
Release 发布分支
Hotfix 生产修复分支
Version tag prefix 是否要添加版本前缀。比如release时,取名版本为0.0.1 这里设置版本前缀为test,则工具在你完成release时到master帮打的tag即为test0.0.1。
重要:任何分支流程commit 后 要finish 该流程,都应该把master 和 develop 更新到最新代码,在finish
一个team 在develop分支上某个版本在开发新的功能,几个新功能开发应该是并行的。所以按照git flow流程这里每个功能都应该单独开辟feature 分支进行开发避免相互影响。
比如要开发一个email相关的功能,下面就git flow的流程
git flow feature start email
# add new file or change something
Git commit -m "this test"
git flow feature finish email
执行后会创建 一个feature/email 并切换过去,我们将在这个分支开发新功能。(可以正常commit 如果被打断也可以stash离开该分支)
当功能开发稳定后,我们pull最新的develop代码,然后回到 feature/email,
git flow feature finish email
执行后会将feature/email merge会develop 分支。并删除feature/email
该功能的使用可以有效的隔离各功能的开发。
git flow bugfix start fixemail
git commit -m "fixemail"
git flow bugfix finish fixemail
流程和2.2.1一致也会创建bugfix/fixemail
git flow release start V0.1.0
#部署到测试环境 进行测试。 有问题提commit修复 但不要merge回develop分支。 Finish 后自动merge到develop 和master分支。
git flow release finish V0.1.0
git push origin master
git push origin [tagname]
#要把tags也推送上去
git flow release start V0.1.0即会创建release/V0.1.0分支
Git flow hotfix 流程
git flow hotfix start V0.1.1
// 行为即为 A new branch 'hotfix/V0.1.1' was created, based on 'master'
git commit -m "fix something"
git flow hotfix finish V0.1.1
会自动打tag 并叫你输入tag描述
执行完finish后的行为
关于其他命令可以敲击git flow 查看帮助