应用 Git 的最佳形式始终存在争议。那是因为 Git 自身只具体阐明了根本的分支操作,这使得它的应用模式: 即分支模型——经常成为用户有意见的中央。尽管Git 分支模型可能帮忙开发者缩小其在更改代码库时带来的抵触。
Git Flow,是一种常常举荐给 Git 用户的分支模型。 兴许一开始你对 Git Flow 的逻辑很感兴趣,然而直到你在实践中遇到了一些阻碍。 毕竟,有有数的变量在起作用,没有一个繁多的分支模型能在所有状况下都能很好地工作。
然而,值的快乐的是作为经典 Git Flow 模型的一个变体,加强的 Git Flow模型版本简化了 Git Flow 中更常见的操作,并保留了次要长处。
经典 Git Flow 模型的辉煌与苦难
自从我发现 Git Flow 在开发具备显著价值产品时是如许杰出以来,我始终是 Git Flow 的强烈倡导者。
一个显著的价值增长须要大量的工夫来证实,就像在基于 scrum 的开发中通常应用的两周以上的 sprint。
当产品仍处于初始开发阶段时,即,没有产品,也没有产品的真正用户时,团队能够把所有的货色都放在主分支中。事实上,这是十分好的:这种策略容许最快的开发速度。然而在生产环境中状况会发生变化。
例如,如果在生产中有一个须要立刻修复的要害 issue,那么对于开发团队来说,为了部署修复的代码而不得不回滚现有曾经实现的代码。在没有进行适当测试的状况下部署代码,不论代码被认为是不成熟的还是开发良好的,显然是不可取的。
这就是分支模型的特点,包含 Git Flow。任何简单的分支模型都应该答复以下问题:
- 如何将下一个版本与人们以后应用的版本隔离开来;
- 如何用下一个版本更新该版本;
- 如何将任何要害谬误的修复代码引入以后版本。
Git Flow 通过拆散“main”分支(生产或“以后版本”分支)和“dev”(开发或“下一个版本”分支)分支,并提供无关应用 feature/release/hotfix
分支的所有规定,来解决这些根本的场景。它无效地解决了 release 的开发工作流中的许多令人头疼的问题。
然而,即便有非常适合经典 Git Flow 模型的我的项目,我也遇到了它可能带来的典型问题:
- Git Flow 很简单,有两个长期存在的分支,三种长期分支,以及分支之间如何解决的严格规定。这种复杂性更容易导致谬误,并减少了修复谬误所需的老本。
- release 和 hotfix 分支须要“双重合并”——进入
main
分支,而后进入devlop
分支。有时你会遗记兼顾两者。您能够应用脚本或 VCS GUI 客户端插件使 Git Flow 分支更容易,但必须首先为给定我的项目中波及的每个开发人员的每台机器设置它们。 - 在 CI/CD 工作流中,一个公布通常会有两个最终版本——一个来自
release
分支自身的最新提交,另一个来自合并提交到main
分支的提交。严格地说,应该应用来自main
的。但这两个通常是雷同的,可能会造成混同。
增强版 Git Flow
在产品的第一次公开公布之前,为了开发工作流的速度和简略性,间接将所有更改提交到 main
分支是相对有意义的。因为还没有产品,所以团队不可能须要尽快修复产品 bug。因而,在这个阶段执行传统 Git Flow 模型所倡议的分支治理是多余的。
而后咱们靠近了最后的 release
版本,在那之后,咱们将不再违心间接提交到 main
分支。咱们停顿得很快,业务优先级没有给建设一个坚如磐石的开发过程留下太多空间。它具备足够的自动化测试,使咱们有信念放弃咱们的次要分支处于筹备公布的状态。
这仿佛是经典 Git Flow 模型的一个无效案例。有了独立的 main
分支和 devlop
分支。
然而,起初我做了一些变动。起初在我看来,对 Git Flow 做一些“补丁”有点过于冒进了。我认为这样可能会突破 Git Flow 次要的思维,从而达不到指标。但通过进一步的思考,我意识到这些调整实际上并没有毁坏 Git Flow。同时,他们解决了下面提到的所有问题,使之成为一个更好的 Git 分支模型。
上面,我将和大家分享这套办法,帮忙开发者克服传统 Git Flow 的毛病。
与传统 Git Flow 的相似之处: 开发隔离
对于加强的 Git Flow 中的工作隔离,依然有两个长期存在的分支:main 和 development。
经典的 Git Flow feature
分支没有正式的命名计划。当 feature
筹备好时,只须要从 devlop
分支进去并合并回去进行开发。团队能够应用任何他们喜爱的命名约定,或者只是心愿开发人员应用比“my-branch”更具备描述性的名称。加强的 Git Flow 也是如此。
压缩合并
我强烈建议在 feature 分支中应用压缩合并,以便在大多数时候保持良好的线性历史记录。如果没有它,当团队同时解决大量的 feature 分支时,git graph(git log -graph
)日志会显得比拟粗率:
但即便你对这种状况下的视觉效果没有意见。没有压缩,提交的历史视图-其中包含一般的 git 日志(没有-graph)和 一些相当不连贯的 log,即便是最简略的合并场景:
应用压缩合并须要晓得的是原有的 feature 分支提交历史会失落。
与经典 Git 流程的区别: Releases and Hotfixes
让咱们来看看公布周期,因为这是你要做的次要事件。当咱们想要公布开发中积攒的内容时,它严格来说是 main 的超集。在此之后,经典和加强的 Git 流之间的最大区别就开始了。
Git Flow 增强版中的 release 分支
在 release 方面,应用加强的 Git Flow 的每一步都与经典的 Git Flow 不同:
- release 是基 于
main
分支的,而不是基于devlop
分支的。你能够用一些有意义的货色标记main
分支的以后的 tip。我采纳了 ISO 8601 格局中基于以后日期的标签,前缀是“v”-例如:v2020-09-09
。
- 如果一天中碰巧有多个版本(例如修补 issue),则格局能够依据须要附加一个间断的数字或字母。
- 请留神,标签通常并不对应于公布日期。它们仅仅是为了迫使 Git 放弃对下一个公布过程开始时
main
分支的参考。
- 应用
git Push origin <the new tag name>
来 push tag。 - 在此之后,可能会有一个意外:如果要删除本地的
main
分支。
- 所有提交到 main 的操作依然是平安的——咱们通过在上一步标记 main 来爱护它们不被垃圾收集。每一个提交(甚至是修补程序)也是开发的一部分。
- 只须要确保团队中只有一个人在执行这一工作:这就是所谓的“公布经理”角色。公布经理通常是最有教训和/或最资深的团队成员,然而团队应该明智地防止任何特定的团队成员永恒地承当这个角色。
- 在开发分支的提醒提交处创立一个新的本地主分支。
- 应用
git Push -force
来推动这个新构造,因为近程仓库不会这么容易地承受这样一个“激烈的变动”。同样,在这种状况下,这并不像看起来那么不平安,因为:
- 咱们只是将主分支指针从一个提交挪动到另一个提交。
- 每次只有一个特定的团队成员在做这个更改。
- 每天的开发工作都在开发分支上进行,所以这样挪动 main 不会烦扰任何人的工作。
- 将其部署到环境中并对其进行测试。任何修复都间接指向主分支,因而它将开始偏离开发分支。
- 与此同时,您能够开始在开发分支中开发新版本,这与在经典 Git Flow 中看到的劣势雷同。
- 当您的新版本被认为足够稳固时,将最终版本部署到生产环境中,并进行一次主开发合并,以取得所有的修复。
加强 Git Flow 模型中的 Hotfixes
Hotfixes 的状况有两方面。如果你正在做一个热修复时,例如,团队正在开发分支中筹备一个新版本,当它们筹备好时,须要部署到生产环境。
作为最初一步,从 main 中抉择提交来开发,以确保下一个版本将蕴含所有修复。如果您须要提交几个热修复程序,您能够通过创立并利用一个补丁而不是屡次抉择补丁来节俭精力—特地是如果您的 IDE 或其余 Git 工具能够提供便当的话。试图在初始版本公布后将合并主分支压缩到开发分支,很可能会与开发分支的独立过程产生抵触,所以我不倡议这样做。
在 relase 期间解决修补程序。例如,当您只是强行推入 main 分支并仍在筹备新版本时,是增强版 Git Flow 中最单薄的中央。依据公布周期的长度和须要解决的问题的重大水平,始终以在新公布版本中蕴含修复为指标——这是最简略的办法,而且基本不会打乱整个工作流。
如果这是一个不可能的,你必须疾速引入一个修复,你不能期待新版本的公布-而后筹备一个有点简单的 Git 过程:
- 创立一个分支—咱们将其称为“new-release”,然而您的团队能够在这里采纳任何命名约定。
- 在您先前为以后 release 创立的标记提交时,删除并从新创立本地主分支。
- 向 main 引入必要的修复,部署到环境,并进行测试。一旦筹备好了,就部署到生产环境中。
- 将以后主版本的更改通过补丁到新版本。
- 而后,从新执行公布过程:在以后骨干的顶端标记并推送标记,在新公布分支的顶端删除并从新创立本地主分支,而后强制推送。
- 您可能不须要后面的标记,所以能够删除它。
- 新公布的分支当初是多余的,所以您也能够删除它。
- 您当初应该能够像平常一样应用新发行版了。通过流传紧急修补程序从主开发通过
cherry pick
或补丁实现。
CI/CD 在加强 Git Flow 模型中的设置
并不是每个我的项目都须要专用的开发环境。在每台开发人员机器上设置简单的本地开发环境可能很容易。
在开发分支上运行测试、测量测试覆盖率和计算复杂性度量,通过在谬误进入执行阶段之前很好地捕捉它们,通常能够升高谬误的老本。
我发现一些 CI/CD 模式在与加强的 Git Flow 联合应用时特地有用:
- 如果您须要一个开发环境,请设置 CI,以便在每次提交到开发分支时进行构建、测试和部署。如果您有 E2E 测试,并且它对您的状况有意义,那么也能够在这里进行 E2E 测试。
- 在每次提交到主分支时,设置 CI 来构建、测试和部署到环境。在这一点上,端到端测试也十分无益。
在两个中央都应用端到端测试仿佛是多余的,然而请记住,修补程序不会在开发过程中产生。在提交到 main 时触发 E2E,将测试修复程序和每天的更改,但在提交到开发时触发将更早地捕捉bug。
- 以一种容许您的团队依据手工申请将构建版本从主环境部署到生产环境的形式配置 CI。
这些模式绝对简略,但提供了反对日常开发操作的弱小机制。
改良和可能存在的限度
加强的 Git Flow 并不适宜所有人。它的确利用了有争议的策略,用武力推动次要分支,所以纯正主义者可能会恼恨它。然而,从理论的角度来看,这并没有什么问题。
如前所述,修补程序在公布期间更具挑战性,但依然是可能的。在适当关注 QA、测试覆盖率等方面,这些不应该常常产生,所以在我看来,与传统的 Git 流相比,加强的 Git 流的整体益处是一个无效的衡量。我很想晓得加强的 Git 流在更大的团队和更简单的我的项目中如何发挥作用,在这些我的项目中修补程序可能会更频繁地呈现。
我对加强的 Git 流模型的踊跃体验也次要围绕着关闭源代码的商业我的项目。这对于一个开源我的项目来说可能是有问题的,因为拉申请通常是基于源代码树的旧版本派生的。解决这个问题没有技术阻碍,只是可能须要比预期更多的致力。我十分欢送那些在开源畛域领有丰盛教训的读者的反馈,因为你们理解加强的 Git 流在这种状况下的适用性。