Git作为一个源代码管理系统,不可避免地涉及到多人协作。协作必须有一个规范的流程,这样大家才能有效的协作,让项目有条不紊的进行。“协同过程”英文称为“workflow”或“flow”,本义是水流。比喻项目像水流一样顺畅自然地向前流动,没有冲击,没有碰撞,更没有漩涡。本文介绍三种广泛使用的协作流程:Git流程Github流程Gitlab流程如果您对Git不是很熟悉,可以先阅读以下文章。《Git 使用规范流程》《常用 Git 命令清单》《Git 远程操作详解》1.特征驱动本文中的三个协作过程有一个共同点:都采用“特征驱动开发”(简称FDD)。意思是需求是开发的起点,先有需求,再有特性分支或hotfix分支。开发完成后,将分支合并到主分支,然后删除。2、Gitflow是最早诞生并被广泛采用的协作过程,这就是Gitflow。2.1特点它有两个主要特点。首先,该项目有两个长期存在的分支。主分支masterdevelopment分支develop前者用于存放对外发布的版本。任何时候你从这个分支得到它,它都是一个稳定的发行版本;后者用于日常开发,存放最新的开发版本。二是项目分三个短期分支。featurebranch,hotfixbranch,releasebranch开发完成后合并到develop或master中,然后删除。关于Git流程的详细介绍,请看我翻译的中文版《Git 分支管理策略》。2.2Git流程评价优点是清晰可控,缺点是相对复杂,需要同时维护两个长期分支。大部分工具默认使用master分支,而开发却在develop分支上进行,导致分支切换频繁,非常烦人。更大的问题在于,这种模式是基于“版本发布”的,目标是在一段时间后产生一个新的版本。但是很多网站项目都是“持续发布”的,代码一改就部署一次。这个时候master分支和develop分支区别不大,也没有必要维护两个长期分支。3、GithubflowGithubflow是Gitflow的简化版,专门为配合“持续发布”而设计。这是Github.com使用的协作过程。3.1Process它只有一个long-term分支,master,所以使用起来非常简单。官方推荐流程如下。 第一步:根据需求,从master上拉取新的分支,不管是function分支还是patch分支。Step2:新分支开发完成后,或者需要讨论的时候,向master发起pullrequest(简称PR)。Step3:PullRequest不仅仅是一个让别人注意到你的请求的通知,更是一个大家共同审阅和讨论你的代码的对话机制。在对话过程中,您还可以不断提交代码。第四步:你的PullRequest被接受,合并到master,重新部署后,你原来拉出的分支会被删除。(也可以先部署再合并。)3.2评估Githubflow最大的优点就是简单。对于“持续发布”的产品来说,可以说是最合适的流程。问题在于它的假设:对master分支的更新与产品发布同时进行。也就是说,master分支的最新代码默认为当前在线代码。然而,有时情况并非如此。将代码合并到master分支中,并不意味着可以立即发布。例如,AppleStore中的一款应用程序在提交审核后,需要一段时间才能上架。这时候如果有新的代码提交,master分支就会和新发布的版本不一致。再比如有些公司有发布窗口,只能在指定的时间发布,这也会导致线上版本滞后于master分支。在上面的例子中,只有一个master分支是不够的。通常,除了master分支之外,您还必须创建一个新的生产分支来跟踪在线版本。4.GitlabflowGitlabflow是Gitflow和Githubflow的结合体。它吸收了两者的优点,既有适应不同开发环境的灵活性,又有单一master分支的简单和方便。这是Gitlab.com上推荐的做法。4.1上游优先级Gitlab流程最好的原则叫做“上游优先”(upsteamfirst),即只有一个主分支master,是所有其他分支的“上游”。只有上游分支采用的代码更改才能应用到其他分支。Chromium项目就是一个例子。明确规定了上游分支为:LinusTorvalds分支子系统(如netdev)分支设备制造商(如三星)分支4.2持续发布Gitlab流程分为两种情况,以适应不同的DevelopmentProcess。对于“持续发布”的项目,建议在master分支之外创建不同的环境分支。比如“开发环境”的分支是master,“预发布环境”的分支是pre-production,“生产环境”的分支是production。开发分支是预发布分支的“上游”,预发布分支是生产分支的“上游”。代码变更必须从“上游”向“下游”发展。比如生产环境出现bug,需要新建一个功能分支,先合并到master,确认没有问题,再cherry-pick到pre-production。进入生产前这一步没有问题。只有在紧急情况下,才允许跳过上游直接并入下游支路。4.3版本发布对于“版本发布”的项目,推荐的做法是从master分支中拉取每个稳定版本的分支,如2-3-stable、2-4-stable等。以后只允许在bug修复的时候将代码合并到这些分支中,此时更新minor版本号。5.一些小技巧5.1PullRequest功能分支合并到master分支必须通过PullRequest(在Gitlab中称为MergeRequest)。如前所述,PullRequest本质上是一种对话机制。提交时可以@relevantpeopleorteams来吸引他们的注意力。5.2Protectedbranchmaster分支应该是保护的,不是每个人都可以修改这个分支,并且有批准PullRequest的权力。Github和Gitlab都提供了“Protectedbranch”的功能。5.3IssueIssue用于bug跟踪和需求管理。建议先新建Issue,再新建相应的功能分支。功能分支总是用于解决一个或多个问题。特性分支的名字可以和issue的名字保持一致,以issue的编号开头,比如“15-require-a-password-to-change-it”。开发完成后,在提交说明中,可以写“fixes#14”或者“closes#67”。Github规定只要commitmessage中有以下动词+数字,对应的issue就会被关闭。closeclosesclosedfixfixedfixedresolveresolvesresolved这个方法也可以一次性关闭多个问题,或者关闭其他代码库的问题。格式为用户名/存储库#issue_number。接受PullRequest后,关闭issue,并删除原来的分支。如果以后重新开issue,新的分支可以沿用原来的名字。5.4合并节点Git有两种合并:一种是“直接合并”(fastforward),不生成单独的合并节点;另一种是“非直接合并”(nonefast-forword),将生成单个节点。前者不利于保持commit信息清晰,也不利于以后的回滚。建议始终使用后者(即使用--no-ff参数)。每当发生合并时,都会有一个合并节点。5.5SquashMultiplecommits为了让其他人更容易阅读你的提交,以及挑选或撤消代码更改,应该在发起PullRequest之前将多个提交合并为一个。(前提是分支只是你自己开发的,还没有和master合并。)这可以通过rebase命令附带的squash操作来完成。具体方法可以参考我写的《Git 使用规范流程》。
