之前一直把Git当做个人版本控制的工具使用,现在由于工作需要,需要多人协作维护文档,所以去简单了解了下Git多人协作的工作流程,发现还真的很多讲解的,而且大神也已经讲解得很清楚了,这里就做一个简单的阅读笔记和指引,推荐后续希望了解Git多人协作工作流程的小伙伴学习。
后文介绍到的Git工作流有以下几种:
从第一个看到最后第七个会感觉有种循环在里面,从最开始就只有一个master分支一个远端仓库(集中式工作流),然后添加feature分支(功能分支工作流),添加develop、release、hotfix分支(Git Flow 工作流),然后到多个远端仓库支持非可信第三方协作(Forking 工作流),然后支持code review等多人讨论、问题跟踪等(Pull Requests 工作流),然后考虑对"持续发布"项目的不友好、删除develop和release分支以默认master分支的最新代码就是当前的线上代码(Github Flow 工作流),然后考虑这种假设很多时候还是不成立、感觉只剩一个master分支太少、为"持续发布"项目增加不同的环境分支如"pre-production"的预生产分支和"production"的生产分支、为"版本发布"项目每个版本拉出一个分支(Gitlab Flow 工作流)。
这篇是看了那么多种工作流中,写得最为全面和详细的一篇,介绍了上面说的5种工作流,感觉Pull Request可能不能算一种工作流?因为它可以和其他的工作流结合,贯穿所有这几种工作流始终。
在阅读的过程中请记住,本文中的几种工作流是作为方案指导而不是条例规定。在展示了各种工作流可能的用法后,你可以从不同的工作流中挑选或揉合出一个满足你自己需求的工作流。
集中式工作流以中央仓库作为项目所有修改的单点实体。工作流只用到master这一个分支。所有修改提交到这个分支上。
工作流程(简化版,详细的特别是第5步需要看原文):
使用多人协作Git工作流的关键,一定是要养成 先pull后push 的节奏,每次想要push之前,一定要 先拉后推。
另一篇文中介绍:
这种工作流比较 适合小团队,因为小团队可能不会太多的协作和合流的动作。
功能分支工作流以集中式工作流为基础,不同的是为各个新功能分配一个专门的分支来开发。这样可以在把新功能集成到正式项目前,用Pull Requests的方式讨论变更。
功能分支工作流背后的核心思路是所有的功能开发应该在一个专门的分支,而不是在master分支上。 这个隔离可以方便多个开发者在各自的功能上开发而不会弄乱主干代码。 另外,也保证了master分支的代码一定不会是有问题的,极大有利于集成环境。
功能开发隔离也让pull requests工作流成功可能, pull requests工作流能为每个分支发起一个讨论,在分支合入正式项目之前,给其它开发者有表示赞同的机会。 另外,如果你在功能开发中有问题卡住了,可以开一个pull requests来向同学们征求建议。 这些做法的重点就是,pull requests让团队成员之间互相评论工作变成非常方便!
功能分支除了可以隔离功能的开发,也使得通过Pull Requests讨论变更成为可能。 一旦某个开发者完成一个功能,不是立即合并到master,而是push到中央仓库的功能分支上并发起一个Pull Request请求,将修改合并到master。 在修改成为主干代码前,这让其它的开发者有机会先去Review变更。
Code Review是Pull Requests的一个重要的收益,而Pull Requests则是讨论代码的一个通用方式。 你可以把Pull Requests作为专门给某个分支的讨论。这意味着可以在更早的开发过程中就可以进行Code Review。
功能分支工作流比上面的集中工作流多出的两点亮点:
Gitflow工作流通过为 功能开发 、 发布准备 和 维护 分配独立的分支,让发布迭代过程更流畅。严格的分支模型也为 大型项目提供了一些非常必要的结构。
虽然比功能分支工作流复杂几分,但提供了用于一个健壮的用于管理大型项目的框架。
相对于使用仅有的一个master分支,Gitflow工作流使用两个分支来记录项目的历史。master分支存储了正式发布的历史,而develop分支作为功能的集成分支。 这样也方便master分支上的所有提交分配一个版本号。
每个新功能位于一个自己的分支,这样可以push到中央仓库以备份和协作。 但功能分支不是从master分支上拉出新分支,而是使用develop分支作为父分支。当新功能完成时,合并回develop分支。 新功能提交应该从不直接与master分支交互。
从各种含义和目的上来看,功能分支加上develop分支就是功能分支工作流的用法。但Gitflow工作流没有在这里止步。
一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从develop分支上checkout一个发布分支。 新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上—— 这个分支只应该做Bug修复、文档生成和其它面向发布任务。 一旦对外发布的工作都完成了,发布分支合并到master分支并分配一个版本号打好Tag。 另外,这些从新建发布分支以来的做的修改要合并回develop分支。
使用一个用于发布准备的专门分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。 这也打造定义良好的开发阶段(比如,可以很轻松地说,『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看到)。
常用的分支约定:用于新建发布分支的分支: develop
用于合并的分支: master
分支命名: release-* 或 release/*
维护分支或说是热修复(hotfix)分支用于给产品发布版本(production releases)快速生成补丁,这是唯一可以直接从master分支fork出来的分支。 修复完成,修改应该马上合并回master分支和develop分支(当前的发布分支),master分支应该用新的版本号打好Tag。
为Bug修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。 你可以把维护分支想成是一个直接在master分支上处理的临时发布。
相比于前面集中式工作流(只有1个master分支)和功能分支工作流(1个master和多个feature分支),Git Flow 工作流瞬间增加了3种不同的分支:develop、release、hotfix。当增加这三种分支之后,整个的工作流程变得比较复杂,每种分支的作用也有一点不同。
从这个时间点开始之后新的功能不能再加到这个分支上—— 这个分支只应该做Bug修复、文档生成和其它面向发布任务。
,如果按照这里理解的话,应该是说直接在release分支上进行一些bug修复和小规模的修改和完善(达不到需要建立分支的程度?感觉如果bug比较大可能会需要建立分支吧,甚至如果更大的bug可能会把release分支又和develop分支合并,继续在develop上面做开发才行)。而如果release分支的发布工作全部准备好了,则会合并到master分支打上一个tag,同时合并回develop,同时删除release分支,如果要求code review,这是一个发起 Pull Request 的理想时机
,即准备正式发布到master和合并到develop上。 。使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。
这句话有点点不懂,如果一个团队在release分支上完善当前的发布版本,另一个团队只能就着之前并不太完善的develop分支进行下一个版本功能的开发,最后如果从release分支合并回develop时,那就是一个完善的上一个版本和添加了许多新功能的不太完善的版本,感觉可能会产生比较多的冲突,合并分支的时候会比较麻烦。除非新功能等代码块模块化做得很好,可能会比较好一些吧。另外release分支的命名一般也会加上版本号or描述性的名称,毕竟它也只是一个中间版本,并不是最终的发布版。release分支是清理发布、执行所有测试、更新文档和其它为下个发布做准备操作的地方,像是一个专门用于改善发布的功能分支。只要创建这个分支并push到中央仓库,这个发布就是 **功能冻结** 的。任何不在develop分支中的新功能都推到下个发布循环中。
做个小结,整体来说,master、develop是贯穿整个项目始终的永远不会被删除的分支,而feature功能分支在功能完成之后就会被合并到develop中,该分支就可以删掉;而release发布分支也是当发布准备完成后,发布到master,合并到develop后就可以删掉;而hotfix维护分支更是在修改维护完成之后,发布到master,合并到develop即可删除。其中release分支和feature分支可以同时进行,通过限定软件版本实现的功能,在版本范围内的,就在release中完善,而在版本范围外的就在新feature功能分支中进行下一个版本的开发,这里存在一个并行开发的流程。
Forking工作流是分布式工作流,充分利用了Git在分支和克隆上的优势。可以安全可靠地管理大团队的开发者(developer),并能接受不信任贡献者(contributor)的提交。
不是使用单个服务端仓库作为『中央』代码基线,而让各个开发者都有一个服务端仓库。这意味着各个代码贡献者有2个Git仓库而不是1个:一个本地私有的,另一个服务端公开的。
主要优势是,贡献的代码可以被集成,而不需要所有人都能push代码到仅有的中央仓库中。 开发者push到自己的服务端仓库,而只有项目维护者才能push到正式仓库。 这样项目维护者 可以接受任何开发者的提交,但无需给他正式代码库的写权限。能为 大型、自发性的团队(包括了不受信的第三方) 提供灵活的方式来安全的协作。
要提交本地修改时,push提交到自己公开仓库中 —— 而不是正式仓库中。 然后,给正式仓库发起一个pull request,让项目维护者知道有更新已经准备好可以集成了。 对于贡献的代码,pull request也可以很方便地作为一个讨论的地方。
集成功能到正式代码库,维护者pull贡献者的变更到自己的本地仓库中,检查变更以确保不会让项目出错, 合并变更到自己本地的master分支, 然后pushmaster分支到服务器的正式仓库中。 到此,贡献的提交成为了项目的一部分,其它的开发者应该执行pull操作与正式仓库同步自己本地仓库。
『官方』仓库的叫法只是一个约定,理解这点很重要。 从技术上来看,各个开发者仓库和正式仓库在Git看来没有任何区别。 事实上,让正式仓库之所以正式的唯一原因是它是项目维护者的公开仓库。
各个开发者应该用分支隔离各个功能,就像在功能分支工作流和Gitflow工作流一样。 唯一的区别是这些分支被共享了。在Forking工作流中这些分支会被pull到另一个开发者的本地仓库中,而在功能分支工作流和Gitflow工作流中是直接被push到正式仓库中。
相比前面介绍的工作流只用了一个origin远程别名指向中央仓库,Forking工作流需要2个远程别名 —— 一个指向正式仓库,另一个指向开发者自己的服务端仓库。别名的名字可以任意命名,常见的约定是使用origin作为远程克隆的仓库的别名 (这个别名会在运行git clone自动创建), upstream(上游)作为正式仓库的别名。
保持本地仓库和正式仓库的同步更新。
由于开发者应该都在专门的功能分支上工作,pull操作结果会都是快进合并。
开发者要通知项目维护者,想要合并他的新功能到正式库中。 Bitbucket和Stash提供了Pull Request按钮,弹出表单让你指定哪个分支要合并到正式仓库。 一般你会想集成你的功能分支到上游远程仓库的master分支中。
这个工作流实际上就是在功能分支工作流之上引入另一个抽象层。 不是直接通过单个中央仓库来分享分支,而是把贡献代码发布到开发者自己的服务端仓库中。
感觉这种工作流其实就是Github使用的工作流(但和后文调研发现看到的Github Flow不同):如果有人想要对某个开源项目做贡献,就 Fork-Push-Pull Request,维护者审核OK,合并变更提交到正式仓库。感觉这个工作流最大的优势就是最初所说的分布式,而且可以接受不可信任的第三方提交代码,而不会影响到原本的代码。其次需要注意的一点是,如果是Fork正式仓库后,要添加功能,一定要自建feature分支进行修改,然后提交Pull Request给维护者,这样才能够进行快速合并。
这个工作流和上面3种工作流最大的区别在于远端的同样的仓库有多个,每个开发者都有一个远端仓库,而前面三种工作流其实远端都只有一个仓库。正如文中所说『官方』仓库的叫法只是一个约定,理解这点很重要。 从技术上来看,各个开发者仓库和正式仓库在Git看来没有任何区别。 事实上,让正式仓库之所以正式的唯一原因是它是项目维护者的公开仓库。
Pull requests是Bitbucket提供的让开发者更方便地进行协作的功能,提供了友好的Web界面可以在提议的修改合并到正式项目之前对修改进行讨论。
开发者向团队成员通知功能开发已经完成,Pull Requests是最简单的用法。 开发者完成功能开发后,通过Bitbucket账号发起一个Pull Request。 这样让涉及这个功能的所有人知道要去做Code Review和合并到master分支。
Pull Request远不止一个简单的通知,而是为讨论提交的功能的一个专门论坛。 如果变更有任何问题,团队成员反馈在Pull Request中,甚至push新的提交微调功能。 所有的这些活动都直接跟踪在Pull Request中。
这种分享提交的形式有助于打造一个更流畅的工作流。
当要发起一个Pull Request,你所要做的就是请求(Request)另一个开发者(比如项目的维护者) 来pull你仓库中一个分支到他的仓库中。这意味着你要提供4个信息以发起Pull Request: 源仓库、源分支、目的仓库、目的分支。
Pull Request可以和功能分支工作流、Gitflow工作流或Forking工作流一起使用。 但一个Pull Request要求 要么分支不同要么仓库不同,所以不能用于集中式工作流。【因为集中式工作流只有一个master分支一个远程仓库……】
基本的过程是这样的:开发者在本地仓库中新建一个专门的分支开发功能。
开发者push分支修改到公开的Bitbucket仓库中。
开发者通过Bitbucket发起一个Pull Request。
团队的其它成员review code,讨论并修改。
项目维护者合并功能到官方仓库中并关闭Pull Request。
在功能分支工作流中使用Pull Request:功能分支工作流用一个共享的Bitbucket仓库来管理协作,开发者在专门的分支上开发功能。 但不是立即合并到master分支上,而是在合并到主代码库之前开发者应该开一个Pull Request发起功能的讨论。功能分支工作流只有一个公开的仓库,所以Pull Request的目的仓库和源仓库总是同一个。 通常开发者会指定他的功能分支作为源分支,master分支作为目的分支。收到Pull Request后,项目维护者要决定如何做。如果功能没问题,就简单地合并到master分支,关闭Pull Request。 但如果提交的变更有问题,他可以在Pull Request中反馈。之后新加的提交也会评论之后接着显示出来。在功能还没有完全开发完的时候,也可能发起一个Pull Request。 比如开发者在实现某个需求时碰到了麻烦,他可以发一个包含正在进行中工作的Pull Request。 其它的开发者可以在Pull Request提供建议,或者甚至直接添加提交来解决问题。
在Gitflow工作流中使用Pull Request:Gitflow工作流和功能分支工作流类似,但围绕项目发布定义一个严格的分支模型。 在Gitflow工作流中使用Pull Request让开发者在发布分支或是维护分支上工作时, 可以有个方便的地方对关于发布分支或是维护分支的问题进行交流。
在Forking工作流中使用Pull Request:在Forking工作流中,开发者push完成的功能到他自己的仓库中,而不是共享仓库。 然后,他发起一个Pull Request,让项目维护者知道他的功能已经可以Review了。在这个工作流,Pull Request的通知功能非常有用, 因为项目维护者不可能知道其它开发者在他们自己的仓库添加了提交。Pull Request的源仓库和目标仓库不是同一个。 源仓库是开发者的公开仓库,源分支是包含了修改的分支。 如果开发者要合并修改到正式代码库中,那么目标仓库是正式仓库,目标分支是master分支。Pull Request也可以用于正式项目之外的其它开发者之间的协作。 比如,如果一个开发者和一个团队成员一起开发一个功能,他们可以发起一个Pull Request, 用团队成员的Bitbucket仓库作为目标,而不是正式项目的仓库。 然后使用相同的功能分支作为源和目标分支。
如果需要小明以外的人审核批准代码,可以把这些人填在【Reviewers】文本框中。
Pull Request并不是为了替代任何 基于Git的协作工作流, 而是它们的一个便利的补充,让团队成员间的协作更轻松方便。
在后文的其他帖子中有看到只介绍了前面四种工作流,最后的Pull Request感觉被集成到了前面的4种工作流当中,作为一种讨论、解决、跟踪、及时反馈的工具。
在企业开发中,使用 Git 作为版本控制软件最看重的还是结合公司自己搭建的 Gitlab,将 Code Review 加入打包部署持续集成的流程中,这样,代码开发完成,提交测试前,便可以对开发人员提交的代码进行 Review,发现潜在的问题,及时指导,对于新人来讲,也能更快更好的学习。
master:master永远是线上代码,最稳定的分支,存放的是随时可供在生产环境中部署的代码,当开发活动告一段落,产生了一份新的可供部署的代码时,发布成功之后,代码才会由 aone2 提交到 master,master 分支上的代码会被更新。应用上 aone2 后禁掉所有人的 master的写权限
develop:保存当前最新开发成果的分支。通常这个分支上的代码也是可进行每日夜间发布的代码,只对开发负责人开放develop权限。
feature: 功能特性分支,每个功能特性一个 feature/ 分支,开发完成自测通过后合并入 develop 分支。可以从 master 或者develop 中拉出来。
hotfix: 紧急bug分支修复分支。修复上线后,可以直接合并入master。
develop 作为固定的持续集成和发布分支,并且分支上的代码必须经过 CodeReview 后才可以提交到 Develop 分支。它的基本流程如下:
每一个需求/变更都单独从Master上创建一条Branch分支;
用户在这个Branch分支上进行Codeing活动;
代码达到发布准入条件后aone上提交Codereview,Codereview通过后代码自动合并到Develop分支;
待所有计划发布的变更分支代码都合并到Develop后,系统再 rebase master 代码到Develop 分支,然后自行构建,打包,部署等动作。
应用发布成功后Aone会基于Develop分支的发布版本打一个“当前线上版本Tag”基线;
应用发布成功后Aone会自动把Develop分支的发布版本合并回master;
整体感觉如果是企业开发大型项目的话,还是主要参照Git Flow的多分支进行的一些微调,虽然这种工作流比较复杂,但是对于大型项目的管理来说比较有用,而且也适合快速迭代开发。
后面有对开发工作流的一些讨论,支持看一下原文,而且里面有一些图,讲解的更为详细,很不错。
这篇介绍了使用较高的3种工作流:Git Flow、Github Flow、Gitlab Flow。里面有一些需要注意的地方:
Git Flow 的作者 Vincent Driessen 非常建议,合并分支的时候,加上 no-ff 参数,这个参数的意思是不要选择 Fast-Forward 合并方式,而是策略合并,策略合并会让我们多一个合并提交。这样做的好处是保证一个非常清晰的提交历史,可以看到被合并分支的存在。
master 分支每合并一个分支,无论是 hotfix 还是 release ,都会打一个版本标签。通过箭头可以清楚的看到分支的开始和结束走向,例如 feature 分支从 develop 开始,最终合并回 develop ,hoxfixes 从 master 检出创建,最后合并回 develop 和 master,master 也打上了标签。
里面对Github Flow工作流中的Pull Request和issue tracking有一些介绍,这部分还不是特别有经验,后面慢慢尝试使用。
这里对Git Flow & GitHub Flow 的瑕疵进行了分析,然后对GitLab Flow进行了介绍,它基于前两者的缺点进行了一些优化,感觉这算是比较新的工作流(因为没有在最上面的那个全的里面被列出来)。主要解决了3个问题:
版本的延迟发布–Prodution Branch:master 分支不够,于是添加了一个 prodution 分支,专门用来发布版本。
不同环境的部署–Environment Branches & Upstream First:每个环境,都对应一个分支,例如下图中的 pre-production 和 prodution 分支都对应不同的环境,我觉得这个工作流模型比较适用服务端,测试环境,预发环境,正式环境,一个环境建一个分支。比较适用服务端,测试环境,预发环境,正式环境,一个环境建一个分支。要注意,代码合并的顺序,要按环境依次推送,确保代码被充分测试过,才会从上游分支合并到下游分支。除非是很紧急的情况,才允许跳过上游分支,直接合并到下游分支。这个被定义为一个规则,名字叫 “upstream first”,翻译过来是 “上游优先”。
版本发布分支–Release Branches & Upstream First:只有当对外发布软件的时候,才需要创建 release 分支。在 Git Flow ,版本记录是通过 master 上的 tag 来记录。发现问题,创建 hotfix 分支,完成之后合并到 master 和 develop。在 GitLab Flow ,建议的做法是每一个稳定版本,都要从master分支拉出一个分支,比如2-3-stable、2-4-stable等等。发现问题,就从对应版本分支创建修复分支,完成之后,先合并到 master,才能再合并到 release 分支,遵循 “上游优先” 原则。
感觉Gitlab Flow说是解决了前面的两种工作流的缺点,它的两种适用场景分别是"持续发布"和"版本发布"的项目;然后搜了下,发现这里是阮一峰大神写的工作流介绍。里面说:
Git flow的优点是清晰可控,缺点是相对复杂,它是基于"版本发布"的,目标是一段时间以后产出一个新版本。但是,很多网站项目是"持续发布",代码一有变动,就部署一次。这时,master分支和develop分支的差别不大,没必要维护两个长期分支。
Github flow 是Git flow的简化版,专门配合"持续发布"。它是 Github.com 使用的工作流程。Github flow 的最大优点就是简单,对于"持续发布"的产品,可以说是最合适的流程。问题在于它的假设:master分支的更新与产品的发布是一致的。也就是说,master分支的最新代码,默认就是当前的线上代码。可是,有些时候并非如此,代码合并进入master分支,并不代表它就能立刻发布。比如,苹果商店的APP提交审核以后,等一段时间才能上架。这时,如果还有新的代码提交,master分支就会与刚发布的版本不一致。另一个例子是,有些公司有发布窗口,只有指定时间才能发布,这也会导致线上版本落后于master分支。上面这种情况,只有master一个主分支就不够用了。通常,你不得不在master分支以外,另外新建一个production分支跟踪线上版本。
Gitlab flow 的最大原则叫做"上游优先"(upsteam first),即只存在一个主分支master,它是所有其他分支的"上游"。只有上游分支采纳的代码变化,才能应用到其他分支。对于"持续发布"的项目,它建议在master分支以外,再建立不同的环境分支。比如,"开发环境"的分支是master,"预发环境"的分支是pre-production,"生产环境"的分支是production。开发分支是预发分支的"上游",预发分支又是生产分支的"上游"。代码的变化,必须由"上游"向"下游"发展。比如,生产环境出现了bug,这时就要新建一个功能分支,先把它合并到master,确认没有问题,再cherry-pick到pre-production,这一步也没有问题,才进入production。只有紧急情况,才允许跳过上游,直接合并到下游分支。对于"版本发布"的项目,建议的做法是每一个稳定版本,都要从master分支拉出一个分支,比如2-3-stable、2-4-stable等等。以后,只有修补bug,才允许将代码合并到这些分支,并且此时要更新小版本号。
Gitlab Flow官网链接
Git资源集合:这个是从上面这篇的连接看到的,整合了很多的Git相关的学习资料or资源,可以作为后续的学习方向,很6。
GitFlow工作流常用操作流程:这篇是一个公司编写的,详细讲了他们公司是怎么使用Git Flow工作流的。这里把 hotfix 直接取名为 bugfix 了,作用还一致的,就是在发布的master分支上进行bug修复。感觉和上面描述的主要不同在于release分支,上面是说用于做发布前的准备,如文档添加等一些小问题的,这里就直接把release分支作为测试分支了,develop分支开发完成后,直接就在这里做测试,如果发现小bug,就在release分支中进行修复。感觉如果是就是做测试分支了,干嘛不直接叫Test分支好了。不过还是有一些借鉴意义,写得也比较全面,可以参考。
Git 工作流的一些经验分享:这篇其实是最先看到的一篇,对前面4种工作流简单评价了一下,适合简单概念性的入门,能够对每种工作流有个大概的认识,然后再去深入看上面的这篇会更容易理解。他后面的Git Flow工作流的实践简单看了下,最大的特别是hotfix分支不是从master拉的,而是从develop分支拉取的。release分支用于回归测试和bug修复,其他的分支功能和Git Flow上面讲解的差不多。
Git Flow工作流程:也是只对Git Flow工作流进行了介绍,不过里面写了分支的命名规范,感觉不错,可以参考:
主分支名称: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
看了这么多种Git的工作流,感觉比较核心一些共同的思想点如下:
最后回归本源:
在阅读的过程中请记住,本文中的几种工作流是作为方案指导而不是条例规定。在展示了各种工作流可能的用法后,你可以从不同的工作流中挑选或揉合出一个满足你自己需求的工作流。
任何工作流程都只是规范or标准or推荐,但是并不一定适用于所有的项目、所有的场景、所有的开发人员,针对不同的情况,需要灵活调整。