GitFlow 是一种 Git 工作流,这个工作流程围绕着 project 的发布 (release) 定义了一个严格的如何建立分支的模型。它是团队成员遵守的一种代码管理方案 。
Git 建分支是非常 cheap 的,我们可以任意建立分支,对任意分支再分支,分支开发完后再合并。
比较推荐、多见的做法是特性驱动 (Feature Driven) 的建立分支法 (Feature Branch Workflow)。
简而言之,就是每一个特性 (feature) 的开发并不直接在主干上开发,而是在分支上开发,分支开发完毕后再合并到主干上。
这样做的好处是:
1.还处于半成品状态的 feature 不会影响到主干2.各个开发人员之间做自己的分支,互不干扰3.主干永远处于可编译、可运行的状态
GitFlow 则在这个基础上更进一步,规定了如何建立、合并分支,如何发布,如何维护历史版本等工作流程。
在工作场合实施 Git 的时候,有很多种工作流程可供选择,此时反而会让你手足无措。企业团队最常用的一些 Git 工作流程,包括 Centralized Workflow、Feature Branch Workflow、Gitflow Workflow、Forking Workflow。 在你开始阅读之前,请记住:这些 Git 工作流程应被视作为指导方针,而非“铁律”。我们只是想告诉你可能的做法。因此,如果有必要的话,你可以组合使用不同的流程。
分支名称 | 说明 |
---|---|
Production | 生产分支,即 Master 分支。只能从其他分支合并,不能直接修改 |
Release | 发布分支,基于 Develop 分支创建,待发布完成后合并到 Develop 和 Production 分支去 |
Develop | 主开发分支,包含所有要发布到下一个 Release 的代码,该分支主要合并其他分支内容 |
Feature | 新功能分支,基于 Develop 分支创建,开发新功能,待开发完毕合并至 Develop 分支 |
Hotfix | 修复分支,基于 Production 分支创建,待修复完成后合并到 Develop 和 Production 分支去,同时在 Master 上打一个 tag |
Git Flow 的核心就是分支(Branch),通过在项目的不同阶段对分支的不同操作(包括但不限于创建、合并、变基等)来实现一个完整的高效率的工作流程。Git Flow 模型中定义了主分支和辅助分支两类分支。其中主要分支包含主分支和开发分支,用于组织与软件开发、部署相关的活动;辅助分支包含功能分支、预发分支、热修复分支以及其他自定义分支,是为了解决特定的问题而进行的各种开发活动。与主分支不同,这些分支总是有有限的生命时间,因为它们最终将被删除。
主分支上存放的是最稳定的正式版本,并且该分支的代码应该是随时可在生产环境中使用的代码。当一个版本开发完毕后,产生了一份新的稳定的可供发布的代码时,主分支上的代码要被更新。同时,每一次更新,都需要在主分支上打上对应的版本号。
任何人不允许在主分支上进行代码的直接提交,只接受其他分支的合入。原则上主分支上的代码必须是合并自经过多轮测试及已经发布一段时间且线上稳定的预发分支。
master 分支只存放历史发布 (release) 版本的源代码。即用于存放对外发布的版本,任何时候在这个分支获取到的都是稳定的已发布的版本。各个版本通过 tag 来标记。上图里的 v0.1 和 v0.2 就是 tag。
开发分支是主开发分支,其上更新的代码始终反映着下一个发布版本需要交付的新功能。当开发分支到达一个稳定的点并准备好发布时,应该从该点拉取一个预发分支并附上发布版本号。也有人称开发分支为集成分支,因为会基于该分支和持续集成工具做自动化的构建。
开发分支接受其他辅助分支的合入,最常见的就是功能分支,开发一个新功能时拉取新的功能分支,开发完成后再并入开发分支。需要注意的是,合入开发的分支必须保证功能完整,不影响开发分支的正常运行。
develop 分支则用来整合各个 feature 分支。开发中的版本的源代码存放在这里。即用于日常开发,存放最新的开发版。
功能分支一般命名为 Feature/xxx,用于开发即将发布版本或未来版本的新功能或者探索新功能。该分支通常存在于开发人员的本地代码库而不要求提交到远程代码库上,除非几个人合作在同一个功能分支开发。关于这点,Thought Works 洞见上有一篇文章“Git Flow 有害论”做了非常有意思的阐述,文章下的评论也异常激烈。也许该文章的名字可能有失偏颇,但文章的本意以及评论传达了一个观点:功能分支要求足够细粒度以避免成为长期存在的功能分支,应当小步合并而不是一次合并大量代码。
功能分支只能拉取自开发分支,开发完成后要么合并回开发分支,要么因为新功能的尝试不如人意而直接丢弃。
每一个特性 (feature) 都必须在自己的分支里开发,feature 分支派生自 develop 分支。 feature 分支只存在于开发者本地,不能被提交到远程库。当 feature 开发完毕后,要合并回 develop 分支。feature 分支永远不会和 master 分支打交道。
预发分支一般命名为 Release/1.2 (后面是版本号),该分支专为测试—发布新的版本而开辟,允许做小量级的 Bug 修复和准备发布版本的元数据信息(版本号、编译时间等)。通过创建预发分支,使得开发分支得以空闲出来接受下一个版本的新的功能分支的合入。
预发分支需要提交到服务器上,交由测试工程师进行测试,并由开发工程师修复 Bug。同时根据该分支的特性我们可以部署自动化测试以及生产环境代码的自动化更新和部署。
预发分支只能拉取自开发分支,合并回开发分支和主分支。
release 分支不是一个放正式发布产品的分支,你可以将它理解为“待发布”分支。 我们用这个分支干所有和发布有关的事情,比如: 1. 把这个分支打包给测试人员测试 2. 在这个分支里修复 bug 3. 编写发布文档 所以,在这个分支里面绝对不会添加新的特性。 当和发布相关的工作都完成后,release 分支合并回 develop 和 master 分支。 单独搞一个 release 分支的好处是,当一个团队在做发布相关的工作时,另一个团队则可以接着开发下一版本的东西。
热修复分支一般命名为 Hotfix/1.2.1 (后面是版本号),当生产环境的代码(主分支上代码)遇到严重到必须立即修复的缺陷时,就需要从主分支上指定的 tag 版本(比如 1.2)拉取热修复分支进行代码的紧急修复,并附上版本号(比如 1.2.1)。这样做的好处是不会打断正在进行的开发分支的开发工作,能够让团队中负责功能开发的人与负责代码修复的人并行、独立的开展工作。
热修复分支只能从主分支上拉取,测试通过后合并回主分支和开发分支。
一个项目发布后或多或少肯定会有一些 bug 存在,而 bug 的修复工作并不适合在 develop 上做,这是因为 1. develop 分支上包含还未验证过的 feature 2. 用户未必需要 develop 上的 feature 3. develop 还不能马上发布,而客户急需这个 bug 的修复。 这时就需要新建 hotfix 分支,hotfix 分支派生自 master 分支,仅仅用于修复 bug,当 bug 修复完毕后,马上回归到 master 分支,然后发布一个新版本,比如,v0.1.1。 同时 hotfix 也要合并回 develop 分支,这样 develop 分支就能享受到 bug 修复的好处了。