Git Flow工作流程
背景
在多组员,多项目等环境进行协同工作时,如果没有统一规范、统一流程,则会导致额外的工作量,甚至会做无用功。所以要减少版本冲突,减轻不必要的工作,就需要规范化的工作流程。
总则
-统一使用Git作为版本控制的主要工具。
-统一使用GitFlow流程管理控制版本。
提交的准则
1.除了源码相关的东西之外,其他build产生的东西(如:maven的target文件夹,.idea文件夹等),均不能提交进入源码仓库,添加到.gitignore文件中忽略掉。
2.撰写规范的提交说明。一份好的提交说明可以帮助协作者更轻松更有效地配合工作。
3.要严格按照我们指定的流程切换到指定分支,开发相应的功能。
分支简述
我们使用的分支流程:
- 天蓝色圆点所在的线为我们源码的主线(master)。主分支,产品的功能全部实现后,最终在master分支对外发布。
- 天蓝色方形指向的节点就是每一个发布版本的标签(tag)。
- 紫色圆点所在的线为主要分支线(develop)。开发分支,基于master分支克隆,产品的编码工作在此分支进行。
- 橙色圆点所在的线为新功能开发分支线(feature)。功能特征分支,基于develop分支克隆,主要用于多人协助开发场景或探索性功能验证场景,功能开发完毕后合并到develop分支。feature分支可创建多个,属于临时分支,目的实现后可删除分支。
- 绿色圆点所在的线为新版本发布线(release)。测试分支,基于delevop分支克隆,产品编码工作完成后,发布到本分支测试,测试过程中发现的小bug直接在本分支进行修复,修复完成后合并到develop分支。本分支属于临时分支,目的实现后可删除分支。
- 红色圆点所在的线为发布版本bug修复线(hotfix)。Bug修复分支,基于master分支或发布的里程碑Tag克隆,主要用于修复对外发布的分支,收到客户的Bug反馈后,在此分支进行修复,修复完毕后分别合并到develop分支和master分支。本分支属于临时分支,目的实现后可删除分支。
主分支说明
代替原来的单个主线(master),我们使用两个分支来记录源码轨迹:
1.原来的master分支用来记录官方发布轨迹;
2.新的develop分支是一个集成分支,用来记录开发新功能的轨迹。
除了master主线和develop主分支线,其他的分支都是临时的分支,有一定的生命周期的,其余的工作流程分支都是围绕这两个分支之间的区别进行的。
其他分支说明
-新功能分支(Feature Branches)
每一个新的功能都应该创建一个独立的分支,从develop分支中派生出来。当功能完成后,要合并(merged)回develop分支,合并后它的生命周期就结束。新功能分支不会与master分支有直接的交汇。如图:
注意:对于所有意图和目的,新功能分支会合并到develop分支。但是,这个Gitflow工作流不会在此结束。
-发布分支(Release Branches)
一旦开发的功能已经满足发布条件(或预定发布日期接近),应该合并所有满足发布条件的新功能分支到develop分支中,然后,开出一个发布分支(Release),开始准备一个发布版本。在这个分支上,不能再添加新的功能,只有bug修复和该版本为导向的任务。一旦到了发布日期,Release就要合并回master发布,并且,打出版本标签。另外,还需要合并回develop分支。
使用一个专门的分支来准备发布版本,使得一个团队能对当前版本进行抛光,而另一个团队继续为下一个版本的功能做准备。它还创造了良好定义的发展阶段(例如,很容易说,“本周我们正在准备4.0版”,而且真实地看到它在库中的结构)。
-维护分支(Maintenance Branches)
维护分支也就是线上bug修复分支,使用来快速修复生产环境的紧急问题。
这个分支是唯一一个开放过程中直接从master分支派生来的分支。快速的修复问题后,它应该被合并回master和develop(或者当前发布分支),然后,master分支需要打一个版本标签。
一个专门的错误修复开发线,可以让团队在不等待下一个发布周期,导致中断工作流程情况下解决问题。可以将维护分支当做主要的问题修复分支,与master并行。
命名约定
-主分支名称:master
-主开发分支名称:develop
-标签(tag)名称:v*.RELEASE,其中”*“ 为版本号,“RELEASE”大写,如:v1.0.0.RELEASE
-新功能开发分支名称:feature-*or feature/*,其中“*” 为新功能简述,如:feature-item-activity-list
-发布分支名称:release-*or release/*,其中*为版本号,“release”小写,如:release-1.0.0
-master的bug修复分支名称:hotfix-*or hotfix/*,其中*为bug简述,如:hotfix/item-update-bug
工作流程
下面具体演示如何使用工作流来管理版本发布周期。假设我们已经存在或创建了一个源码中央存储仓库。
工作流的基础
创建develop分支
-项目负责人在本地master基础上创建一个develop分支,然后,推送到服务器;
git branch develop
git push -u origin develop
-其他开发人员,需要克隆develop中央仓库的源码,创建一个develop的轨迹版本;如果,已经克隆过该项目,则,不需要执行以下第一条命令。
git clone git@github.org:search-cloud/demo.git
git checkout -b develop origin/develop
develop这个分支将包含项目的完整历史记录,而master将包含缩略版本。
** 假设开始以下所有的流程之前,都已经创建好develop分支。**
新功能开发流程
1.新建feature分支
基于develop分支创建新功能分支:
git checkout -b feature/demo develop
推送到远程仓库,共享:
git push
所有开发此新功能的人员,都在此分支上开发提交代码。
git status git add git commit -m "Add some-file."
2.完成新功能开发(合并feature分支到develop)
当确定新功能开发完成,且联调测试通过,并且新功能负责人已经得到合并feature分支到develop分支的允许;这样才能合并feature分支到develop。
git pull origin develop git checkout develop git merge feature/demo git push git branch -d feature/demo
第一条命令是确保在合并新功能之前,develop分支是最新的。
注意:
-新功能分支,永远不要直接合并到master分支。
-合并可能会有冲突,应该谨慎处理冲突。
3.在测试环境发布develop分支代码(提交测试)
线上版本发布流程
1.从develop中创建准备发布的release分支
当主测试流程完成,源码已经趋近于稳定状态,应该准备一个发布版本,确立版本号:
git checkout -b release-0.1.0 develop
推送到远程仓库共享:
git push
这个分支是清理准备发布、 整体回归测试、 更新文档,和做其他任何系统即将发布的事情。
2.继续抛光改bug
3.release分支合并到master发布
一旦已经满足发布条件(或已经到了预定发布日期),应该把release分支合并到master分支和develop分支中,然后,使用master发布新版本。合并release分支到develop分支是很重要的,要让release上修改的东西能在后续的开发分支中生效。
git checkout master git merge release-0.1.0 git push
4.release分支合并到develop
git checkout develop git merge release-0.1.0 git push git branch -d release-0.1.0
5.打标签
Release分支在功能开发分支(develop)和公共发布版(master)中,充当一个缓冲的作用。每当有源码合并到master中的时候,应该在master上打一个标签,以便后续跟踪查阅。
git tag -a 0.1.0.RELEASE -m "Initial public release" master git push --tags
线上Bug修复流程
当终端用户,反馈系统有bug时,为了处理bug,需要从master中创建出保养分支;等到bug修复完成,需要合并回master:
1.创建hotfix分支
git checkout -b issue-#001 master
2.修改bug Fix the bug
3.完成修复,合并到master发布
git checkout master git merge issue-#001 git push
4.打标签
git tag -a 0.1.1.RELEASE -m "Initial public release" master git push --tags
5.合并到develop
git checkout develop git merge issue-#001 git push
新功能开发工作流
切换到本地仓库工作区
cd /home/timerhunter/workspace
从远程仓库克隆代码到本地仓库
git clone https://xxxx@localhost:8443/r/valve/V5-Lora.$git
基于master分支,创建develop分支
/* 切换到master分支 */ git checkout master /* 基于master分支克隆develop分支,并在克隆完毕后直接跳转到develop分支 */ git checkout -b develop /* 推送develop分支到远程仓库 */ git push origin develop
注:编码工作主要在develop分支,master分支主要用来发布稳定版本
在本地仓库的开发流程
完成一个功能点或者一天的工作结束时,将代码提交到本地仓库
/* 提交修改到缓冲区 */ git add . /* 提交修改到本地仓库 */ /* 如果是修复的BUG,应该在修改说明的最开始添加Bug#ID,多个Bug用逗号分隔,例如Bug#002,003 */ /* 如果是完成了一个指派的任务,应该在修改说明的最开始添加Task#TaskID,例如Task#165 */ git commit -m "Bug#123 修改说明" /* 每完成一个功能点可以对代码进行打包 */ git tag -m "简要说明增加/修复/删除了什么功能" v0.0.0.170718
注:不是每一个Tag都需要提交到远程仓库,比如可以在完成一个功能点的编码工作后未编译就打一个包,仅存储于本地仓库,在编译成功&测试通过后,再打一个新的Tag包(里程碑Tag包),仅将里程碑Tag包推送到远程仓库
推送代码到远程仓库
当完成一个功能点或阶段工作时,将代码推送到远程仓库develop分支
/* 执行代码拉取操作,防止代码冲突 */ git pull /* 解决代码冲突后,推送代码到远程仓库*/ git push origin develop
注:禁止将未编译或编译不通过的代码提交到远程仓库,如果编码工作进行未完成可以提交到本地仓库中,等待该功能点全部实现后再将代码推送到远程仓库中。
将代码发布到测试分支
阶段性的开发工作已完成,启动小批量测试工作,将代码发布到测试分支release
git checkout develop git checkout -b release git push origin release
测试工程师提交Bug后修复
从远程仓库拉取代码
/* 克隆仓库 */ git clone https://admin@192.168.1.88:8443/r/admin/test.$git /* 查看远程仓库分支情况:克隆仓库时只能克隆master分支,因此需要拉取指定分支,我们使用$git branch -r查看远程分支情况 */ git branch -r origin/HEAD -> origin/master origin/dev origin/master origin/release /* 拉取测试分支 */ git checkout -b release origin/release
- 修复流程同#2.4,#2.5;
- 注意在$git commit时的修复说明中添加Bug#BugID关键字
- 完成一个Bug修复或完成阶段性工作后,将代码推送到远程分支
测试工作完成后,合并代码到develop分支
/* 切换到develop分支 */ git checkout develop /* 执行合并操作,将release分支代码合并到develop分支 */ git merge release /* 如果合并报错,则解决冲突,冲突解决后继续再次执行合并 */
开发工作和测试工作都完毕后,发布时将develop分支合并到主线
git checkout master
git merge develop
阶段开发完毕,打一个里程碑Tag包
/* 创建里程碑Tag */ git tag -m "Task#003 v1.0.0 首版发布" v1.0.0.170718 /* 推送里程碑Tag到远程仓库 */ git push origin v1.0.0.170718
发布后的产品Bug修复工作流
查找里程碑Tag
/* 查询里程碑及其提交说明 */ git tag -n1 -l v*
基于里程碑Tag创建分支
/* git checkout -b [创建的分支名称] [里程碑Tag名称] */ git checkout -b bugfix-v1.0.0.170718 v1.0.0.170718
修复代码后可以查询修改过的地方
git diff
修复完毕后分别合并到develop分支和master分支
/* 合并到develop */ git checkout develop git merge hotfix-v1.0.0.170718 /* 提交到远程仓库develop分支 */ git push origin develop /* 合并到master:如果随下一个版本再发布,可不用合并至master分支 */ git checkout master git merge develop /* 提交到远程仓库master分支 */ git push origin master
创建新的里程碑Tag
git tag -m "Bug#002 修复某某Bug" v1.0.1.170719 /* 推送到远程仓库 */ git push origin v1.0.1.170719
删除bugfix分支
/* 删除本地分支-$git branch -d [本地分支名]*/ git branch -d bugfix-v1.0.0.170718 /* 删除远程分支-$git push origin :[远程分支名]*/ git push origin :bugfix-v1.0.0.170718
日常开发过程中常用操作
提交后发现丢了几个文件没有提交
/* 正常提交 */ git commit -m "发布v1.0" /* 发现丢了修改记录,重新添加 */ git add CHANGELOG.md /* 重新提交,仍以"发布v1.0的名义提交",最终只有一个提交*/ git commit --amend
撤销上一次的提交,但是保留暂存区和当前修改不变
/* 正常提交 */ git commit -m "发布v1.0" /* 将会撤销“发布v1.0”的提交,但是保留暂存区和当前目录中文件的修改 */ git reset --soft HEAD~
撤销上一次的提交和暂存区修改,仅保留当前修改不变
/* 正常提交 */ git commit -m "发布v1.0" /* 将会撤销“发布v1.0”的提交,但是保留暂存区和当前目录中文件的修改 */ git reset --mixed HEAD~
撤销上一次的提交,并丢弃所有修改,包括暂存区和当前目录中的修改,整体回档到上上次的提交
/* 正常提交 */ git commit -m "发布v1.0" /* 将会撤销“发布v1.0”的提交,但是保留暂存区和当前目录中文件的修改 */ git reset --hard HEAD~
撤销暂存区和当前目录下所有文件的修改,整体回档到上一次提交
注意:此操作非常危险,会丢失所有修改,直接整体回档到指定的版本,谨慎使用
/* 正常提交 */ git commit -m "发布v1.0" /* 修改多个文件 */ /* 添加到暂存区 */ git add . /* 撤销暂存区和本地目录下所有文件的修改,并整体回档到上一次提交的状态 */ git reset --hard HEAD /* 可以修改HEAD为SHA-1值回档到任意版本 */ /* 使用git log查看每次提交的SHA-1值,可以仅指定前7位 */ git reset --hard 745d8cd
将文件提交到暂存区后撤回
在对文件执行git add操作后,重新撤回
/* 添加文件到暂存区 */ git add README /* 将文件从暂存区撤回 */ git reset HEAD README
撤销对文件的修改
在对文件进行修改后,发现思路不对,需要将文件恢复至原有状态
/* 撤销对CHANGELOG.md文件的修改,请注意这是一个危险的命令, * 对指定文件的修改都会被取消,会还原成上次提交的样子 */ git checkout -- CHANGELOG.md