Git协同工作流介绍
git相关的文章和教程非常多,但是系统介绍和了解工作流的人并不多,在使用过程中用错或用偏的也不少,这里分享的是,假设你已经入门的情况下,我们如何去选择适合团队需要的工作流。
git优势
这里先唠叨git的优势,对比传统的代码管理工具,git至少有以下这些优点:
- 有温度的工具:由 Git 衍生出来的 GitHub/GitLab 可以帮你很好地管理编程工作,比如GitHub包括即时通信功能,开发者可以互相审核、评论和打分。同时还包括 wiki、fork、pull request、issue……集成了与编程相关的工作,让我们的工作可以呈现在一个工作平台上,并以此来规范整个团队的工作。
- 分布式管理:你可以离线提交代码,而不用担心网络问题。
- 合并分支管理:合并分支后也能查看整个代码的变更记录
- 分支快速切换:Git 切换分支的时候通常很快,不像其他版本管理器,比如SVN,每个分支一份拷贝。
git常用命令
跳转这里查看常用命令:常用命令
这里记录自己平时经常使用的一些命令,并不是本文的重点。另外叨叨一下,有些人喜欢在集成的IDE下通过界面方式来进行操作,比如vs code或者eclipse都有傻瓜化的集成,这里推荐使用命令行操作,我觉得有如下一些优势:
- 第一、可以和IDE解耦,不用换一个IDE就要去了解对应界面的使用方法;
- 第二、命令行的操作非常快速,当然缺点是你需要记忆一些命令,但是常用的命令真心不多;
- 第三、命令行拥有界面没有的体验,比如一个简单的git status你可以查看内部更多的详情;git stash命令,可以把当前没有完成的事先暂存一下,然后去忙别的事;git cherry-pick命令可以让你有选择地合并提交。git add -p可以让你挑选改动提交。
git工作流介绍
市面上有以下几种常见的工作流:
- 中心式协同工作流【主干开发】
- 功能分支协同工作流【特性分支】
- github协同工作流
- gitlab协同工作流
- gitflow协同工作流
中心式协同工作流
这种方式等于把git当做svn适用,很多同学估计都是这么用的。这种协同方式是所有的人都在 Master 分支上共享他们的代码。
流程
这里的流程是这样的:
- 从服务器上把代码同步下来;
- 本地编码后,再add/commit到本地仓库
- 最后再push到origin master上
这里的第三步有可能出错,因为可能别人在你之前在相同地方已经提交了代码,这时候你需要先(git pull --rebase)一下,如果发现冲突,就解决冲突然后继续合并(git rebase --continue)。到这里你是否感觉和svn越来越像,每天早上过来定时的update一下,然后再编码,上传代码之前也是这样先update一下,再做上传操作?
焦油坑
这里有几个坑需要注意:
- 代码冲突:建议每天编码之前和代码上传之前不定期、频繁的进行git pull --rebase。
- 代码干扰:随着开发团队规模的扩大,可能你pull一个不可运行的代码下来(push上去的人没有用心检查是否可以编译通过),这时候你的麻烦开始产生了,你要停下手上的活,花费可能很久的时间去把代码编译通过,于是我们经常听到很多开发人员在那边互相抱怨,怎么就不能好好检查后再上传呢,还让不让人写代码,好好学习一下svn怎么用吧……
总结:
中心式的协同显然无法满足团队规模的扩展和代码的干扰冲突,而且产品上线后,master的BUG会直接影响生产环境,也就说master其实是不稳定的,而用不稳定的主干直接和生产环境挂钩,后果可想而知。所以该流程不适用产品线迭代开发和持续更新,如果你只有1-2个开发人员那就罢了,否则一般不建议使用这种方式,接下来就要介绍如何去避免上面的这些焦油坑,也就是我们的功能分支协同工作流上场了。
功能分支协同工作流
上面的那种方式有一个问题,就是大家都在一个主干上开发程序,对于小团队或是小项目你可以这么干,但是对比较大的项目或是人比较多的团队,这么干就会有很多问题。最大的问题就是代码可能干扰太严重。尤其是,我们想安安静静地开发一个功能时,我们想把各个功能的代码变动隔离开来,同时各个功能又会有多个开发人员在开发。
这时,我们不想让各个功能的开发人员都在 Master 分支上共享他们的代码。我们想要的协同方式是这样的:同时开发一个功能的开发人员可以分享各自的代码,但是不会把代码分享给开发其他功能的开发人员,直到整个功能开发完毕后,才会分享给其他的开发人员(也就是进入主干分支),接下来就是我们的功能分支上场了。
流程:
这里的流程是这样的:
- 切割开发分支:从git服务器上clone一份代码下来,并在本地切割出一个分支(git checkout -b jackyfei_dev);
- 编码提交:在分支下进行本地编码,后进行git add和git commit;
- 合并分支:切换到master分支(git checkout master),合并jackyfei_dev分支(git merge jackyfei_dev);
- 推送到服务器:最后push到服务器(git push -u origin master),注意这里推送后不会把分支一起推送到服务器,如果要推送分支上去可以使用命令:git push origin jackyfei_dev;
- 代码重审或代码测试[可选步骤]:代码审查人员或代码测试人员在你的分支上审查或测试通过后,在服务器端进行合并操作。该步骤根据团队大小进行选择,非必做项。
- 删除分支[可选步骤]:这里有点阅后即焚的感觉(git branch -d jackyfei_dev),当然你不删除也无妨,后续可以继续使用。
切割分支:
合并分支:
推送分支:
注意事项
- 删除分支:如果你在还没合并分支的时候,就要进行分支删除操作,git会有一个提示不能删除的操作,如果有重要的代码没有合并,建议不要-D强制删除。
- 分支冲突:在合并的过程会出现冲突,如下图所示,这时候需要手动解决冲突,方式和svn一样。手动合并后,再git add/git commit就可以了。
- 版本同步:这里的master和线上的版本保持同步,所以master必须尽量保证是干净的,稳定的,一般不要轻易去动他。
焦油坑
这里和注意事项不同,罗列的是该协作方式的缺陷:
- 线上出现BUG,本地分支正开发到一半,还没经过测试,无法进行发布,这时该如何解决?
- master无法保证一定是纯净的,因为每个人都可以merge上去
总结:
我们可以看到,其实,这种开发也是以服务器为中心的开发,还不是 Git 分布式开发,它只不过是用分支来完成代码改动的隔离。这里隔离的内容不叫项目而是小功能,这符合了产品快速迭代的需求。
如果团队规模不大,采用这种分支协同反而可能增加不必要的工作,所以要根据团队规模和现实当中的问题进行选型,一般团队超过两个人以上,而且线上环境频繁变更导致经常性的出现不稳定的异常,这种协同方式还是挺不错的。这里要思考的是,如果线上出了问题,本地开发一半无法进行发布的问题该如何处理呢?
GitFlow协同工作流
针对功能分支工作流的不足,GitFlow出现了,该工作流总共有5个分支,而其中的master和developer两个分支需要长期维护,其他的分支都是可以随时“阅后即焚”的。
流程
这里的流程是这样的:
- Feature 分支:也就是功能分支,用于开发功能,其对应的是开发环境,可以“阅后即焚”。
- Developer 分支:是开发分支,一旦功能开发完成,就向Developer 分支合并,合并完成后,删除功能分支。这个分支对应的是集成测试环境。
- Release 分支:当 Developer 分支测试达到可以发布状态时,开出一个 Release 分支来,然后做发布前的准备工作。这个分支对应的是预发环境。之所以需要这个 Release 分支,是我们的开发可以继续向前,不会因为要发布而被 block 住而不能提交。一旦 Release 分支上的代码达到可以上线的状态,那么需要把 Release 分支向 Master 分支和 Developer 分支同时合并,以保证代码的一致性。然后再把 Release 分支删除掉。
- Hotfix 分支:是用于处理生产线上代码的 Bug-fix,每个线上代码的 Bug-fix 都需要开一个 Hotfix 分支,完成后,向 Developer 分支和 Master 分支上合并。合并完成后,删除 Hotfix 分支。
- Master 分支:也就是主干分支,用作发布环境,上面的每一次提交都是可以发布到线上环境的。
主要事项
- 我们需要长期维护 Master 和 Developer 两个分支。
- Release 和 Hotfix 分支需要同时向两个分支作合并。所以,如果没有一个好的工具来支撑的话,这会因为我们可能会忘了做一些操作而导致代码不一致。
- GitFlow 协同虽然工作流比较重。但是它几乎可以应对所有公司的各种开发流程,包括瀑布模型,或是快速迭代模型。
焦油坑
- 分支太多,所以会出现 git log 混乱的局面。
- 在开发得足够快的时候,你会觉得同时维护 Master 和 Developer 两个分支是很太无聊,因为大部分情况下两者都是一样的。
- 管理变得非常复杂。尤其当你想回滚某些人的提交时,你就会发现这事似乎有点儿不好干了。
- 工作过程中,你会来来回回地切换工作的分支,有时候一不小心没有切换,就提交到了不正确的分支上,你还要回滚和重新提交等等。
GitHub Flow
流程
除非你是开源项目或者有购买github企业版,否则一般企业不会把核心代码托管在公共的github上面。
- 开发人员都把github上的代码 fork 到自己的代码仓库中。
- 开发容易代码库有两个远程仓库,一个是自己fork的库,一个是官方的库。
- 开发人员在本地建“功能分支”,在这个分支上做代码开发。
- 开发完成后,功能分支被 push 到开发人员自己的代码仓库中。
- 然后,向“官方库”发起 pull request,并做 Code Review。
- 一旦通过,就向官方库进行合并。
焦油坑
- GitHub Flow 这种玩法虽然变得很简单,但是没能把我们的代码和运行环境给联系在一起。
GitLab Flow
流程
以上是引入环境分支流程:
- 从master分支拉取一个预发布环境分支
- 从预发布环境分支拉取一个生产环境分支
流程虽然简单,但是增加分支后都是工作量,如果有很好的引入CI/CD,其实这一步也是多余的。以上主要是针对2C的互联网业务,2B的要看情况来处理,实时性没有那么强。
以上是引入版本分支流程:
对于版本和代码分支的问题,我觉得这应该是有意义的,但是,最好不要维护太多的版本,版本应该是短暂的,等新的版本发布时,老的版本就应该删除掉了。
总结
总之,GitFlow大而全,但是很重;中心式协同流简单但扩展性不好;功能分支和GitHub协同流轻量灵活(无须关注环境和多版本),适应性强大(既能适应快速开发和迭代,也适应CI/CD),个人倾向使用这功能分支协同工作流。当然没有一招鲜吃遍天的银弹,具体选择什么协作流程还是要具体分析,比如GitFlow的这种流程,可以考虑把Release分支裁剪掉,保证轻量化的同时,也能满足实际流程的需要;中心式的流程增加版本分支,也能很好的管理产品的版本代码。
当我们把精力放在软件架构和开发流程优化上,我们的git协同流会变得更加简单,所以与其熟练玩弄git协同流,不如放心思放在架构和开发流程的优化上,这才有事倍功半的效果。最后附上对比图,供你选择和参考,如果你们的团队有更好的用法,请多赐教。
Git协同工作流介绍的更多相关文章
- 【Slickflow学习】.NET开源工作流介绍、下载(一)
第一次自己写博客文章,大家多多指教.写博客主要记录一下学习的过程,给初学者提供下参考,也留给自己做备忘. Slickflow .NET开源工作流-介绍 这里摘录Slickflow官网的介绍: Slic ...
- 通达OA 小飞鱼开发培训第四讲 工作流介绍(图文)
本次课程主要解说了OA工作流相关内容,有些涉及到工作流的程序开发假设对工作流不熟悉也是有非常大难度,因此在这里进行了内容补充. 1.工作流介绍
- 【git】------git的基本介绍及linux的基本命令------【巷子】
001.git简介 git是一款开源的分布式版本控制工具 在世界上所有的分布式版本控制工具中,git是最快.最简单.最流行的 git的起源 作者是Linux之父:Linus Benedict Torv ...
- git 工作流介绍
GIT Git工作流你可以理解为工作中团队成员遵守的一种代码管理方案,在Git中有以下几种工作流方案作为方案指导: 集中式工作流 功能开发工作流 Gitflow工作流 Forking工作流 下面针对性 ...
- Git flow 工作流与规范
概述 简版图: PS. 可能用到的命令: 1.从指定 commit拉出新分支 git checkout commitId -b 本地新branchName git checkout 9fbc3d0 ...
- git flow工作流
https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md 说明: 个人在学习Git工作流的过程中,从原有的 SVN 模 ...
- git的基本介绍和使用
前言:从事iOS开发一年多以来,一直使用svn管理源代码.对svn的特点和弊端已经深有体会.前些天双十二前后,项目工期紧张到爆,起早贪黑的加班,可谓披星戴月,这还不止,回到家中还要疯狂的敲代码.那么问 ...
- 转载:CODE CSDN Git 配制方法介绍
以前一直使用Github,最近看到CSDN出了CODE代码托管功能,由于国内的阿里云服务器很稳定,而且不会被国 墙,所以果断的迁移了,下面就简单的介绍一下CODE的配置使用.其实CSDN的code 何 ...
- git的基础介绍和使用
git工作原理 git的工作原理还是比较简单的,当我们创建了本地代码仓库后,会在本地代码仓库的根目录中生成一个.git的隐藏文件. .git为一个文件目录,又叫做版本库.在本地代码仓库文件夹中,除.g ...
随机推荐
- SpringMVC SessionAttributes 简述
使用SpringMVC时,我们会发现网络上有关SessionAttributes注解的内容非常少,更多的人甚至推荐你继续用HttpServletRequest中的session管理方法来控制Sessi ...
- 【转】java中PriorityQueue优先级队列使用方法
优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最高优先权的元素. PriorityQueue是从JDK1.5开始提供的新的数据结构接口. 如果不提供Comparator的话,优先 ...
- redis的持久化之RDB的配置和原理
Redis优秀的性能是由于其将所有的数据都存储在内存中,同样memcached也是这样做的,内存中的数据会在服务器重启后就没有了,也就是不能保证持久化.但是为什么Redis能够脱颖而出呢,很大程度上是 ...
- Spring Boot实战笔记(五)-- Spring高级话题(Spring Aware)
一.Spring Aware Spring 依赖注入的最大亮点就是你所有的 Bean 对 Spring容器的存在是没有意识的.即你可以将你的容器替换成其他的容器,如Google Guice,这时 Be ...
- 十七、Hadoop学记笔记————Hbase入门
简而言之,Hbase就是一个建立在Hdfs文件系统上的数据库(mysql,orecle等),不同的是Hbase是针对列的数据库 Hbase和普通的关系型数据库区别如下: Hbase有一些基本的术语,主 ...
- box-shadow 详解及示例
box-shadow [bɑks] - [ˈʃædoʊ] 英文示意: box:盒,包厢 shadow:阴影,渐变 定义: box-shadow: none | <shadow> ...
- java 基础之枚举
问题:对象的某个属性的值不能是任意的,必须为固定的一组取值其中的某一个 解决办法: 1) 在setGrade方法中做判断,不符合格式要求就抛出异常 2) 直接限定用户的选择,通过自定义类模拟枚举的 ...
- 最新的爬虫工具requests-html
使用Python开发的同学一定听说过Requsts库,它是一个用于发送HTTP请求的测试.如比我们用Python做基于HTTP协议的接口测试,那么一定会首选Requsts,因为它即简单又强大.现在作者 ...
- Connection reset by peer的常见原因
1,如果一端的Socket被关闭(或主动关闭,或因为异常退出而 引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer). Socket默认连接60秒 ...
- 安装Navicat for MySQL
注: 以下内容引自 https://www.cnblogs.com/da19951208/p/6403607.html Navicat for MySQL下载.安装与破解 一:下载Navicat ...