欢迎您的光临,本博所发布之文章皆为作者亲测通过,如有错误,欢迎通过各种方式指正。

文摘  Git工作流、GitFlow工作流使用讲解

开发工具 本站 1288 0评论

一、什么是Git工作流?


Git工作流你可以理解为工作中团队成员遵守的一种代码管理方案,在Git中有以下几种工作流方案作为方案指导:

· 集中式工作流

· 功能开发工作流

· Gitflow工作流

· Forking工作流


下面针对性说下每个工作流可能使用到的场景和适用性:


集中式工作流

集中式工作流 | center

这种工作方式跟svn类似,它只有一个master分支,开发者会先把远程的仓库克隆到本地,之后的修改和提交都在本地操作,直到在某个合适的时间点将本地的代码合入到远程master。这种工作流比较适合小团队,因为小团队可能不会太多的协作和合流的动作。


功能开发工作流

image.png

这种工作流关注功能开发,不直接往master提交代码保证它是稳定并且干净的,而是从master拉取feature分支进行功能开发,团队成员根据分工拉取不同的功能分支来进行不同的功能开发,这样就可以完全隔离开每个人的工作。当功能开发完成后,会向master分支发起Pull Request,只有审核通过的代码才真正允许合入master,这样就加强了团队成员之间的代码交流,也就是我们常说的Code Review。


Gitflow工作流


image.png

这个工作流其实也是我们团队采用的工作流,这也是很多团队会采用的工作流,它会相对复杂一点,但它非常适合用来管理大型项目的发布和维护,后面笔者也会详细讲下这一块。贯穿整个开发周期,master和develop分支是一直存在的,master分支可以被视为稳定的分支,而develop分支是相对稳定的分支,特性开发会在feature分支上进行,发布会在release分支上进行,而bug修复则会在hotfix分支上进行。笔者也是花了不少时间才熟练掌握整个工作流,期间遇到不少坑,后面会跟大家分享下。


Forking工作流


image.png

Forking工作流对于开源项目贡献者一定不陌生了,它有一个公开的中央仓库,其他贡献者可以Fork(克隆)这个仓库作为你自己的私有仓库,开源项目维护者可以直接往中央仓库push代码,而代码贡献者只能将代码push到自己的私有仓库,只有项目维护者接受代码贡献者往中央仓库发起的pull request才会真正合入。


二、Git工作流指南:Gitflow工作流


在你开始阅读之前,请记住:流程应被视作为指导方针,而非“铁律”。我们只是想告诉你可能的做法。因此,如果有必要的话,你可以组合使用不同的流程

444-git-workflows-gitflow.png


Gitflow工作流定义了一个围绕项目发布的严格分支模型。虽然比功能分支工作流复杂几分,但提供了用于一个健壮的用于管理大型项目的框架。


Gitflow工作流没有用超出功能分支工作流的概念和命令,而是为不同的分支分配一个很明确的角色,并定义分支之间如何和什么时候进行交互。除了使用功能分支,在做准备、维护和记录发布也使用各自的分支。当然你可以用上功能分支工作流所有的好处:Pull Requests、隔离实验性开发和更高效的协作


工作方式

Gitflow工作流仍然用中央仓库作为所有开发者的交互中心。和其它的工作流一样,开发者在本地工作并push分支到要中央仓库中。


历史分支

相对使用仅有的一个master分支,Gitflow工作流使用2个分支来记录项目的历史。master分支存储了正式发布的历史,而develop分支作为功能的集成分支。这样也方便master分支上的所有提交分配一个版本号。

555-git-workflow-release-cycle-1historical.png

剩下要说明的问题围绕着这2个分支的区别展开。


功能分支

每个新功能位于一个自己的分支,这样可以push到中央仓库以备份和协作。但功能分支不是从master分支上拉出新分支,而是使用develop分支作为父分支。当新功能完成时,合并回develop分支。新功能提交应该从不直接与master分支交互。

666-git-workflow-release-cycle-2feature.png

注意,从各种含义和目的上来看,功能分支加上develop分支就是功能分支工作流的用法。但Gitflow工作流没有在这里止步。


发布分支

777-git-workflow-release-cycle-3release.png

一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从develop分支上fork一个发布分支。新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上 —— 这个分支只应该做Bug修复、文档生成和其它面向发布任务。一旦对外发布的工作都完成了,发布分支合并到master分支并分配一个版本号打好Tag。另外,这些从新建发布分支以来的做的修改要合并回develop分支。

使用一个用于发布准备的专门分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。

这也打造定义良好的开发阶段(比如,可以很轻松地说,『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看到)。


常用的分支约定:

用于新建发布分支的分支: develop

用于合并的分支: master

分支命名: release-* 或 release/*


维护分支

888-git-workflow-release-cycle-4maintenance.png

维护分支或说是热修复(hotfix)分支用于生成快速给产品发布版本(production releases)打补丁,这是唯一可以直接从master分支fork出来的分支。修复完成,修改应该马上合并回master分支和develop分支(当前的发布分支),master分支应该用新的版本号打好Tag。

为Bug修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。你可以把维护分支想成是一个直接在master分支上处理的临时发布。


示例


下面的示例演示本工作流如何用于管理单个发布循环。假设你已经创建了一个中央仓库。


1)创建开发分支

999-git-workflow-release-cycle-5createdev.png

第一步为master分支配套一个develop分支。简单来做可以本地创建一个空的develop分支,push到服务器上:

git branch develop

git push -u origin develop

以后这个分支将会包含了项目的全部历史,而master分支将只包含了部分历史。其它开发者这时应该克隆中央仓库,建好develop分支的跟踪分支:

git clone ssh://user@host/path/to/repo.git

git checkout -b develop origin/develop

现在每个开发都有了这些历史分支的本地拷贝。


2)工程师A和工程师B开始开发新功能

100-git-workflow-release-cycle-6maryjohnbeginnew.png

这个示例中,工程师A和工程师B开始各自的功能开发。他们需要为各自的功能创建相应的分支。新分支不是基于master分支,而是应该基于develop分支:

git checkout -b some-feature develop

他们用老套路添加提交到各自功能分支上:编辑、暂存、提交:

git status

git add

git commit


3)工程师A完成功能开发

101-git-workflow-release-cycle-7maryfinishes.png

添加了提交后,工程师A觉得她的功能OK了。如果团队使用Pull Requests,这时候可以发起一个用于合并到develop分支。否则她可以直接合并到她本地的develop分支后push到中央仓库:

git pull origin develop

git checkout develop

git merge some-feature

git push

git branch -d some-feature

第一条命令在合并功能前确保develop分支是最新的。注意,功能决不应该直接合并到master分支。冲突解决方法和集中式工作流一样。


4)工程师A开始准备发布

102-git-workflow-release-cycle-8maryprepsrelease.png

这个时候工程师B正在实现他的功能,工程师A开始准备她的第一个项目正式发布。像功能开发一样,她用一个新的分支来做发布准备。这一步也确定了发布的版本号:

git checkout -b release-0.1 develop

这个分支是清理发布、执行所有测试、更新文档和其它为下个发布做准备操作的地方,像是一个专门用于改善发布的功能分支。


只要工程师A创建这个分支并push到中央仓库,这个发布就是功能冻结的。任何不在develop分支中的新功能都推到下个发布循环中。


5)工程师A完成发布

103-git-workflow-release-cycle-9maryfinishes.png

一旦准备好了对外发布,工程师A合并修改到master分支和develop分支上,删除发布分支。合并回develop分支很重要,因为在发布分支中已经提交的更新需要在后面的新功能中也要是可用的。另外,如果工程师A的团队要求Code Review,这是一个发起Pull Request的理想时机。

git checkout master

git merge release-0.1

git push

git checkout develop

git merge release-0.1

git push

git branch -d release-0.1

发布分支是作为功能开发(develop分支)和对外发布(master分支)间的缓冲。只要有合并到master分支,就应该打好Tag以方便跟踪。

git tag -a 0.1 -m "Initial public release" master

git push --tags

Git有提供各种勾子(hook),即仓库有事件发生时触发执行的脚本。可以配置一个勾子,在你push中央仓库的master分支时,自动构建好对外发布。


6)最终用户发现Bug

104-git-workflow-gitflow-enduserbug.png

对外发布后,工程师A回去和工程师B一起做下个发布的新功能开发,直到有最终用户开了一个Ticket抱怨当前版本的一个Bug。为了处理Bug,工程师A(或工程师B)从master分支上拉出了一个维护分支,提交修改以解决问题,然后直接合并回master分支:

git checkout -b issue-#001 master

Fix the bug

git checkout master

git merge issue-#001

git push


就像发布分支,维护分支中新加这些重要修改需要包含到develop分支中,所以工程师A要执行一个合并操作。然后就可以安全地删除这个分支了:

git checkout develop

git merge issue-#001

git push

git branch -d issue-#001


最后

Git是一个不错的版本管理工具,但也仅仅是工具。记住,这里演示的工作流只是可能用法的例子,而不是在实际工作中使用Git不可违逆的条例。所以不要畏惧按自己需要对工作流的用法做取舍。不变的目标就是让Git为你所用。


三、GitFlow工作流常用操作流程


1. 主要分支介绍


888-git-workflow-release-cycle-4maintenance.png

1.1 master分支

主分支,产品的功能全部实现后,最终在master分支对外发布。


1.2 develop分支

开发分支,基于master分支克隆,产品的编码工作在此分支进行。


1.3 release分支

测试分支,基于delevop分支克隆,产品编码工作完成后,发布到本分支测试,测试过程中发现的小bug直接在本分支进行修复,修复完成后合并到develop分支。本分支属于临时分支,目的实现后可删除分支。


1.4 bugfix分支

Bug修复分支,基于master分支或发布的里程碑Tag克隆,主要用于修复对外发布的分支,收到客户的Bug反馈后,在此分支进行修复,修复完毕后分别合并到develop分支和master分支。本分支属于临时分支,目的实现后可删除分支。


1.5 feature分支

功能特征分支,基于develop分支克隆,主要用于多人协助开发场景或探索性功能验证场景,功能开发完毕后合并到develop分支。feature分支可创建多个,属于临时分支,目的实现后可删除分支。


2. 新功能开发工作流


2.1 切换到本地仓库工作区

cd /home/timerhunter/workspace


2.2 从远程仓库克隆代码到本地仓库

$git clone https://xxxx@localhost:8443/r/valve/V5-Lora.$git


2.3 基于master分支,创建develop分支

/* 切换到master分支 */

$git checkout master

/* 基于master分支克隆develop分支,并在克隆完毕后直接跳转到develop分支 */

$git checkout -b develop

/* 推送develop分支到远程仓库 */

$git push origin develop


注:编码工作主要在develop分支,master分支主要用来发布稳定版本


2.4 在本地仓库的开发流程

完成一个功能点或者一天的工作结束时,将代码提交到本地仓库


/* 提交修改到缓冲区 */

$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包推送到远程仓库


2.5 推送代码到远程仓库

当完成一个功能点或阶段工作时,将代码推送到远程仓库develop分支


/* 执行代码拉取操作,防止代码冲突 */

$git pull

/* 解决代码冲突后,推送代码到远程仓库*/

$git push origin develop


注:禁止将未编译或编译不通过的代码提交到远程仓库,如果编码工作进行未完成可以提交到本地仓库中,等待该功能点全部实现后再将代码推送到远程仓库中。


2.6 将代码发布到测试分支

阶段性的开发工作已完成,启动小批量测试工作,将代码发布到测试分支release

$git checkout develop

$git checkout -b release

$git push origin release


2.7 测试工程师提交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修复或完成阶段性工作后,将代码推送到远程分支


2.8 测试工作完成后,合并代码到develop分支

/* 切换到develop分支 */

$git checkout develop

/* 执行合并操作,将release分支代码合并到develop分支 */

$git merge release

/* 如果合并报错,则解决冲突,冲突解决后继续再次执行合并 */


2.9 开发工作和测试工作都完毕后,发布时将develop分支合并到主线

$git checkout master

$git merge develop


2.10 阶段开发完毕,打一个里程碑Tag包

/* 创建里程碑Tag */

$git tag -m "Task#003 v1.0.0 首版发布" v1.0.0.170718

/* 推送里程碑Tag到远程仓库 */

$git push origin v1.0.0.170718


3. 发布后的产品Bug修复工作流


3.1 获取Bug产品的软件发布版本号


3.2 查找里程碑Tag

 /* 查询里程碑及其提交说明 */

 $git tag -n1 -l v*


3.3 基于里程碑Tag创建分支

 /* git checkout -b [创建的分支名称] [里程碑Tag名称] */

 $git checkout -b bugfix-v1.0.0.170718 v1.0.0.170718


3.4 修复代码后可以查询修改过的地方

 $git diff


3.5 修复完毕后分别合并到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


3.6 创建新的里程碑Tag

 $git tag -m "Bug#002 修复某某Bug" v1.0.1.170719

 /* 推送到远程仓库 */

 $git push origin v1.0.1.170719


3.7 删除bugfix分支

/* 删除本地分支-$git branch -d [本地分支名]*/

$git branch -d bugfix-v1.0.0.170718

/* 删除远程分支-$git push origin :[远程分支名]*/

$git push origin :bugfix-v1.0.0.170718


4. 日常开发过程中常用操作


4.1 撤销操作


4.1.1 提交后发现丢了几个文件没有提交

/* 正常提交 */

$git commit -m "发布v1.0"

/* 发现丢了修改记录,重新添加 */

$git add CHANGELOG.md

/* 重新提交,仍以"发布v1.0的名义提交",最终只有一个提交*/

$git commit --amend


4.1.2 撤销上一次的提交,但是保留暂存区和当前修改不变

/* 正常提交 */

$git commit -m "发布v1.0"

/* 将会撤销“发布v1.0”的提交,但是保留暂存区和当前目录中文件的修改 */

$git reset --soft HEAD~


4.1.3 撤销上一次的提交和暂存区修改,仅保留当前修改不变

/* 正常提交 */

$git commit -m "发布v1.0"

/* 将会撤销“发布v1.0”的提交,但是保留暂存区和当前目录中文件的修改 */

$git reset --mixed HEAD~


4.1.4 撤销上一次的提交,并丢弃所有修改,包括暂存区和当前目录中的修改,整体回档到上上次的提交

/* 正常提交 */

$git commit -m "发布v1.0"

/* 将会撤销“发布v1.0”的提交,但是保留暂存区和当前目录中文件的修改 */

$git reset --hard HEAD~


4.1.5 撤销暂存区和当前目录下所有文件的修改,整体回档到上一次提交

注意:此操作非常危险,会丢失所有修改,直接整体回档到指定的版本,谨慎使用


/* 正常提交 */

$git commit -m "发布v1.0"

/* 修改多个文件 */

/* 添加到暂存区 */

git add .

/* 撤销暂存区和本地目录下所有文件的修改,并整体回档到上一次提交的状态 */

$git reset --hard HEAD

/* 可以修改HEAD为SHA-1值回档到任意版本 */

/* 使用git log查看每次提交的SHA-1值,可以仅指定前7位 */

$git reset --hard 745d8cd


4.1.6 将文件提交到暂存区后撤回

在对文件执行git add操作后,重新撤回


/* 添加文件到暂存区 */

$git add README

/* 将文件从暂存区撤回 */

$git reset HEAD README


4.1.7 撤销对文件的修改

在对文件进行修改后,发现思路不对,需要将文件恢复至原有状态


/* 撤销对CHANGELOG.md文件的修改,请注意这是一个危险的命令,

 * 对指定文件的修改都会被取消,会还原成上次提交的样子 */

$git checkout -- CHANGELOG.md


目前仅用到这些流程,新学有不足的地方请指出交流。


四、Git 团队协作的一些命令


1.开分支

git branch 新分支名

例如,在master分支下,新开一个开发分支:

git branch dev


2.切换到新分支

git checkout 分支名

例如,在master分支下,切换到新开的dev:

git checkout dev


3.开分支和切换分支合并到一个命令

git checkout -b 新分支名

例如,新开一个开发分支,并立即切换到该分支:

git checkout -b dev


4.切换回原分支

git checkout 原分支名

例如,切换回master

git checkout master

注意:当前分支有修改,还未commit的时候,会切换失败,应当先commit,但可以不用push


5.合并分支

git merge 需要合并的分支名

例如,刚刚已经切换回master,现在需要合并dev的内容:

git merge dev

建议在GitLab(或者其他git系统)上面创建merge request的形式来进行分支的合并和代码审核。


6.查看本地分支列表

git branch -a

前面带remotes/origin 的,是远程分支


7.查看远程分支列表

git branch -r


8.向远程提交本地新开的分支

git push origin 新分支名

例如,刚刚在master下新开的dev分支:

git push origin dev


9.删除远程分支

git push origin :远程分支名

例如,删除刚刚提交到远程的dev分支:

git push origin :dev


10.删除本地分支

git branch 分支名称 -d

例如,在master分支下,删除新开的dev分支:

git branch dev -d

注意:如果dev的更改,push到远程,在GitLab(或者其他git系统)上面进行了merge操作,但是本地master没有pull最新的代码,会删除不成功,可以先git pull origin master,或者强制删除

git branch dev -D


11.更新分支列表信息

git fetch -p


12.TortoiseGit(乌龟git)

不可否认,在windows下,这个是个不错的工具。不管你是命令行新手还是重度使用者,我觉得都可以尝试一下。


参考网址:

https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md 

https://blog.csdn.net/zsm180/article/details/75291260 

https://blog.csdn.net/wwj_748/article/details/55226044 

https://www.cnblogs.com/myqianlan/p/4195994.html 

https://www.cnblogs.com/claireyuancy/p/7008258.html 


转载请注明: ITTXX.CN--分享互联网 » Git工作流、GitFlow工作流使用讲解

最后更新:2018-12-05 09:33:33

赞 (11) or 分享 ()
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽