1.gitflow 介绍
比如我很喜欢的git stash
命令,可以把当前没有完成的事先暂存一下,然后去忙别的事。git cherry-pick
命
令可以让你有选择地合并提交。git add -p
可以让你挑选改动提交,git grep $regexp $(git rev-list --all)
可以用
来在所有的提交中找代码。因为都是本地操作,所以你会觉得速度飞快。
除此之外,由 Git 衍生出来的 GitHub/GitLab 可以帮你很好地管理编程工作,比如 wiki、fork、pull
request、issue……集成了与编程相关的工作,让人觉得这不是一个冷冰冰的工具,而真正和我们的日常
工作发生了很好的交互。
GitHub/GitLab 这样工具的出现,让我们的工作可以呈现在一个工作平台上,并以此来规范整个团队的工
作,这才正是 Git 这个版本管理工具成功的原因。
中心式协同工作流
首先,我们先说明一下,Git 是可以像 SVN 这样的中心工作流一样工作的。我相信很多程序员都是在采用这样的工作方式。
这个过程一般是下面这个样子的。
- 从服务器上做
git pull origin master
把代码同步下来。 - 改完后,
git commit
到本地仓库中。 - 然后
git push origin master
到远程仓库中,这样其他同学就可以得到你的代码了。
如果在第 3 步发现 push 失败,因为别人已经提交了,那么你需要先把服务器上的代码给 pull 下来,为了避免有 merge 动作,你可以使用 git pull --rebase
。这样就可以把服务器上的提交直接合并到你的代码中,对此,Git 的操作是这样的。
- 先把你本地提交的代码放到一边。
- 然后把服务器上的改动下载下来。
- 然后在本地把你之前的改动再重新一个一个地做 commit,直到全部成功。
如下图所示。Git 会把 Origin/Master 的远程分支下载下来(紫色的),然后把本地的 Master 分支上的改动一个一个地提交上去(蓝色的)。
如果有冲突,那么你要先解决冲突,然后做 git rebase --continue
。如下图所示,git 在做 pull --rebase
时,会一个一个地应用(apply)本地提交的代码,如果有冲突就会停下来,等你解决冲突。
功能分支协同工作流
上面的那种方式有一个问题,就是大家都在一个主干上开发程序,对于小团队或是小项目你可以这么干,但是对比较大的项目或是人比较多的团队,这么干就会有很多问题。
最大的问题就是代码可能干扰太严重。尤其是,我们想安安静静地开发一个功能时,我们想把各个功能
的代码变动隔离开来,同时各个功能又会有多个开发人员在开发。
这时,我们不想让各个功能的开发人员都在 Master 分支上共享他们的代码。我们想要的协同方式是这
样的:同时开发一个功能的开发人员可以分享各自的代码,但是不会把代码分享给开发其他功能的开发
人员,直到整个功能开发完毕后,才会分享给其他的开发人员(也就是进入主干分支)。
因此,我们引入“功能分支”。这个协同工作流的开发过程如下。
- 首先使用
git checkout -b new-feature
创建 “new-feature”分支。 - 然后共同开发这个功能的程序员就在这个分支上工作,进行 add、commit 等操作。
- 然后通过
git push -u origin new-feature
把分支代码 push 到服务器上。 - 其他程序员可以通过
git pull --rebase
来拿到最新的这个分支的代码。 - 最后通过 Pull Request 的方式做完 Code Review 后合并到 Master 分支上。
就像上面这个图显示的一样,紫色的分支就是功能分支,合并后就会像上面这个样子。
GitFlow协同工作流
在真实的生产过程中,前面的协同工作流还是不能满足工作的要求。这主要因为我们的生产过程是比较
复杂的,软件生产中会有各式各样的问题,并要面对不同的
环境。我们要在不停地开发新代码的同时,维护线上的代码,于是,就有了下面这些需求。
- 希望有一个分支是非常干净的,上面是可以发布的代码,上面的改动永远都是可以发布到生产环境中的。这个分支上不能有中间开发过程中不可以上生产线的代码提交。
- 希望当代码达到可以上线的状态时,也就是在 alpha/beta release 时,在测试和交付的过程中,依然可以开发下一个版本的代码。
- 最后,对于已经发布的代码,也会有一些 Bug-fix 的改动,不会将正在开发的代码提交到生产线上去。
为了解决这些问题,GitFlow 协同工作流就出来了。
这个协同工作流的核心思想如下图所示。
整个代码库中一共有五种分支。
-
Master 分支。也就是主干分支,用作发布环境,上面的每一次提交都是可以发布的。
-
Feature 分支。也就是功能分支,用于开发功能,其对应的是开发环境。
-
Developer 分支。是开发分支,一旦功能开发完成,就向 Developer 分支合并,合并完成后,删除功能分支。这个分支对应的是集成测试环境。
-
Release 分支。当 Developer 分支测试达到可以发布状态时,开出一个 Release 分支来,然后做发布前的准备工作。这个分支对应的是预发环境。之所以需
要这个 Release 分支,是我们的开发可以继续向前,不会因为要发布而被 block 住而不能提交。
一旦 Release 分支上的代码达到可以上线的状态,那么需要把 Release 分支向 Master 分支和
Developer 分支同时合并,以保证代码的一致性。然后再把 Release 分支删除掉。
-
Hotfix 分支。是用于处理生产线上代码的 Bug-fix,每个线上代码的 Bug-fix 都需要开一个 Hotfix 分支,完成后,向 Developer 分支和 Master 分支上合并。
合并完成后,删除 Hotfix 分支。
这就是整个 GitFlow 协同工作流的工作过程。我们可以看到:
-
我们需要长期维护 Master 和 Developer 两个分支。
-
这其中的方式还是有一定复杂度的,尤其是 Release 和 Hotfix 分支需要同时向两个分支作合并。所以,如果没有一个好的工具来支撑的话,这会因为我们可
能会忘了做一些操作而导致代码不一致。
-
GitFlow 协同虽然工作流比较重。但是它几乎可以应对所有公司的各种开发流程,包括瀑布模型,或是快速迭代模型。
Gitflow 协同工作流的缺点
其中有个问题就是因为分支太多,所以会出现 git log 混乱的局面。具体来说,主要是 git-flow 使用`git
merge --no-ff`来合并分支,在 git-flow 这样多个分支的
环境下会让你的分支管理的 log 变得很难看。如下所示,左边是使用–no-ff 参数在多个分支下的问题。
所谓--no-ff
参数的意思是——no fast forward
的意思。也就是说,合并的方法不要把这个分支的提交以前
置合并的方式,而是留下一个 merge 的提交。这是
把双刃剑,我们希望我们的--no-ff
能像右边那样,而不是像左边那样。
对此的建议是:只有 feature 合并到 developer 分支时,使用–no-ff 参数,其他的合并都不使用--no-ff
参
数来做合并。
另外,还有一个问题就是,在开发得足够快的时候,你会觉得同时维护 Master 和 Developer 两个分支
是一件很无聊的事,因为这两个分支在大多数情况下都是一
样的。包括 Release 分支,你会觉得创建的这些分支太无聊。
而你的整个开发过程也会因为这么复杂的管理变得非常复杂。尤其当你想回滚某些人的提交时,你就会
发现这事似乎有点儿不好干了。而且在工作过程中,你会来来回回地切换工作的分支,有时候一不小心
没有切换,就提交到了不正确的分支上,你还要回滚和重新提交,等等。
2 分支详细介绍
首先有一个 master 版本,如果新开发一个功能,则会创建一个 develop 分支
我们现在想开发一个新功能,glodstyle , 改变界面的皮肤,分别创建对应的分支
再开发一个小游戏功能,分别创建对应的分支
如果线上跑的程序出现bug了,创建一个热修复分支。
修复bug以后,尽快合并到master中。同时修复的版本,也要合并到 develop 分支上
两个功能分支继续往前推进,feature_goldstyle 先开发完成,合并到 develop 分支上
feature_goldstyle 完成后,合并到 develop 分支,然后基于 develop分支 创建预发布分支(release) ,在设个分支上进行上线前的测试。
如果 release 分支出现bug,则直接在 release 分支上进行发布,修复以后,合并到master分支上。
开发分支也需要这个功能,也要合并到开发分支上。
然后 小游戏分支也开发完成了,合并到 develop分支上,然后创建 release 分支,如果测试没问题,则
合并到master分支上。
hotfix 分支 修复完bug 后,直接就删除了。
也可以不需要 release 分支
直接在develop 分支上进行测试
分支类型
-
master 主分之(生产环境分支),确保任何时刻该分之上的代码都是可发布的稳定的,不允许直接提交代码到该分支。为实现更严格的控制可以添加权限,只有
主程序员才可操作该分支,普通开发员无权限
-
develop 开发分支,该分支上的代码是开发完成且经过测试(自测)的代码。在多人协作开发的场景下不建议直接在该分支上提交代码应该配合功能分支、预发
布分支和补丁分支来进行代码的合并
-
feature/FEATURE_NAME 功能分支
-
release/vSEMATIC_VERSION 预发布分支
-
hotfix/HOTFIX_NAME 补丁分支
-
vMAJOR.MINOR.PATCH 版本标签
分支说明
分支类型 | 定义 | 作用 | 合并关系 | 建立时机 | 初始代码来源 |
---|---|---|---|---|---|
master | 主分支 | 记录每一个正式发布版本,TAG所在分支 | 允许来自release和hotfix分支的合并 | 仓库初始化 | 仓库初始化 |
develop | 开发分支 | 保持最新的经过自测的代码 | 允许来自feature、release和hotfix分支的合并 | master创建完成后 | master |
release | 预发布分支 | 表示预发布在测试QA环境的分支,待测试人员进行测试 | 不允许来自任何分支的合并 | develop上代码满足发布要求 | 推荐使用develop上最新的commit |
feature | 功能分支 | 开发独立的功能需求 | 不允许来自任何分支的合并 | 有独立的新功能需求时 | 推荐使用develop上最新的commit |
hotfix | 补丁分支 | 修复已发布版本的bug | 不允许来自任何分支的合并 | 已发布版本出现BUG时 | master(或master上的TAG) |
1.2.1 历史分支
相对使用仅有的一个master分支,Gitflow工作流使用2个分支来记录项目的历史。master分支存储了正
式发布的历史,而develop分支作为功能的集成分支。 这样也方便master分支上的所有提交分配一个版
本号。
1.2.2 功能分支
每个新功能位于一个自己的分支,这样可以push到中央仓库以备份和协作。 但功能分支不是从master分
支上拉出新分支,而是使用develop分支作为父分支。当新功能完成时,合并回develop分支。 新功能提
交应该从不直接与master分支交互。
注意,从各种含义和目的上来看,功能分支加上develop分支就是功能分支工作流的用法。但Gitflow工作
流没有在这里止步。
1.2.3 发布分支
一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从develop分支上fork
一个发布分支。 新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分
支上—— 这个分支只应该做Bug修复、文档生成和其它面向发布任务。 一旦对外发布的工作都完成了
发布分支合并到master分支并分配一个版本号打好Tag。 另外,这些从新建发布分支以来的做的修改要
合并回develop分支。(最后再删除Release分支)使用一个用于发布准备的专门分支,使得一个团队可以
在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。 这也打造定义良好的开发阶
段(比如,可以很轻松地说,『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看
到)。
常用的分支介绍
用于新建发布分支的分支: develop
用于合并的分支: master
分支命名: release-* 或 release/*
1.2.4 维护分支
维护分支或说是热修复(hotfix)分支用于生成快速给产品发布版本(production releases)打
补丁,这是唯一可以直接从master分支fork出来的分支。 修复完成,修改应该马上合并回master分支和
develop分支(当前的发布分支),master分支应该用新的版本号打好Tag。为Bug修复使用专门分支,
让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。 你可以把维护分支想成是一个直
接在master分支上处理的临时发布。
1.3 GItFlow的实现
1.3.1 使用命令来实现
2.然后clone 项目
3.为master分支配套一个develop 分支,简单来说,可以在本地创建一个空的 develop 分支,push到服务器上
git checkout -b develop #基于当前分支
初始化项目工程,创建 springBoot 项目
提交分支到服务器上
git push --set-upstream origin develop
初始化框架,加上springBoot 框架及样例
以后这个分支将会包含了项目的全部历史,而master分支将包含了部分历史。其他开发者这时
应该克隆中央仓库,建好develop分支的跟踪分支:
4.创建功能分支- 程序员A
git clone http://192.168.53.197:3000/root/gitflow.git
git checkout develop # 切换到develop分支
git checkout -b feature/FEATURE-01 # 基于develop 分支创建功能分支
git push -u origin feature/FEATURE-01
做功能修改,添加功能
提交
程序员A完成了开发的功能。如果团队 使用Pull requests ,这时候发起一个用于合并到develop分
支。
否则可以直接合并到他本地的develop分支后push 到中央仓库
# 拉取远程的develop分支,并且当前分支(本地分支some-feature)合并上远程分支develop
#第一条命令在合并功能前确保develop分支是最新的。注意,功能决不应该直接合并到master分支。 冲突解决方法和集中式工作流一样。
git pull origin develop
git checkout develop
git merge --no-ff feature/FEATURE-01 #合并分支到develop分支上
git push
# 删除本地分支
git branch -d feature/FEATURE-01
# 如果在服务器上有这个分支,则需要执行以下命令
git push origin --delete feature/FEATURE-01
创建功能分支程序员B:
git clone http://192.168.50.197:3000/root/gitflow.git
git checkout develop # 切换到develop分支
git checkout -b feature/FEATURE-02 #
功能开发完成后,需要合并分支
# 拉取远程的develop分支,并且当前分支(本地分支some-feature)合并上远程分支develop
#第一条命令在合并功能前确保develop分支是最新的。注意,功能决不应该直接合并到master分支。 冲突解决方法和集中式工作流一样。
git pull origin develop
git checkout develop
git merge --no-ff feature/FEATURE-01 #合并分支到develop分支上
git push
# 删除本地分支
git branch -d feature/FEATURE-02
6.在develop分支上创建 release 分支
这时候开始第一个项目的正式发布。像功能开发,用一个分支来做发布准备。
git checkout develop
git checkout -b release/v0.9.0
这个分支是清理发布、执行所有测试、更新文档和其它为下个发布做准备操作的底仓
测试人员进行测试
开发人员进行修复测试问题
git add .
git commit -m "fix:fix some ... "
如果测试没有问题,则合并到master分支上
一旦准备好了对外发布,就需要合并修改到master分支上和develop分支上。删除发布分支。
合并回develop分支很重要,因为在发布分支中已经提交的更新需要在后面的新功能中也要是可
用的。另外,如果团队要求 Code Review ,这时一个发起Pull Request 的李想时机。
git checkout master
git merge --no-ff release/v0.9.0
git push
# 把release 版本也合并到develop分支上
git checkout develop
git merge --no-ff release/v0.9.0
git push
git branch -d release-0.1.0
# If you pushed branch to origin:
git push origin --delete release-0.1.0
发布分支是作为功能开发(develop分支)和对外发布(master分支)间的缓冲。只要有合并到master
分支,就应该打好Tag以方便跟踪。
git tag -a v0.9.0 -m "Initial public release" master
git push --tags
Git 有提供各种钩子(hook) , 即仓库有事件发生时触发执行的脚本。可以配置一个钩子,在你push
中央仓库的master 分支上时,自动构建好对外发布。
7.如果master在生产环境上出现bug
git checkout master
git checkout -b hotfix/v0.9.0
进行修复 bug
8.把修复的版本合并到master 分支上
git checkout master
git merge --no-ff hotfix/v0.9.0
git tag v0.9.1
git push
git push origin v0.9.1
# 把补丁分支 合并到develop 分支上
git checkout develop
git merge --no-ff hotfix/v0.9.0
git push
git branch -d hotfix/v0.9.0
1.3.2 使用source tree 来实现
1.首先在gitlab上创建一个项目
2.在source tree 创建分支
在本地把服务器上的项目拉下来
# 用命令行创建develop分支
git checkout -n develop
git push --set-upstream origin develop
然后用 source tree打开
创建 feature-01分支
对feature-01 分支 进行 修改上传
可以在此页面进行提交,点击 + 号
功能开发完成后,该怎么办呢?
再次点击git工作流:
点击完成功能
一般情况下,不会选择在开发分支上进行变基
点击确定
再次点击 GIt 工作流,创建预发布版本,一般在develop 分支上。
点击确定
如果预发布版本测试没有问题,则再次点击Git 工作流,完成发布版本
点击确定:
加入我们在生产环境上出现bug,补丁分支是基于master的
修复完成后,再次点击GIt 工作流
1.3.3 使用gitlab实现git flow
可以安装 git flow 插件
-
首先在 gitlab 上创建仓库
把仓库代码拉到本地
创建develop 分支
# clone 项目
git clone http://192.168.50.197:82/rorm_group/recas.git
# 创建develop 分支 并切换分支
git checkout -b develop
# 添加和修改文件
# 把develop 分支提交到服务器
git push --set-upstream origin develop
设置 master 和 develop 为保护分支,且只有 master 角色才能 merge 和 push
2.成员进行clone git clone
添加成员
3.项目组长分配里程碑与议题
创建完成如下:
下面是创建issue
添加完成后,就可以在里程碑中看到添加的问题
可以指派人解决
4.项目成员根据自己被分配的任务建立对应的分支
- 先在项目中建立分支,再拉取开发
- 先在本地建立分支,再提交
# 拉取代码
# clone 项目
git clone http://192.168.53.197:82/rorm_group/xx.git
# 创建develop 分支 并切换分支
git checkout -b question01
# 添加和修改文件
# 把develop 分支提交到服务器
git push --set-upstream origin question1
然后编辑文件
git add .
git commit -m "ddd"
git push origin feature/question01
开发人员完成开发后,在 gitlab 上 创建MergeRequest
-
fixes #xxx
-
fixed #xxx
: 关闭某一issue -
fix #xxx
-
closes #xxx
-
close #xxx
-
closed #xxx
: 关闭某一issue
点击 修改分支
点击提交合并请求。
用管理员用户登录,右上角有合并请求
点击进去