问题背景
Git flow和Github flow及其问题
使用GitLab flow
目录
什么是GitLab工作流
功能分支
生产分支
使用GitLab flow环境分支
使用GitLab flow发布分支
使用GitLab flow合并/拉取请求
使用GitLab flow进行问题跟踪
链接和关闭合并请求中的问题
用rebase压缩提交
减少功能分支中的合并提交
经常投入并频繁推动
如何写一个好的提交信息
合并前进行测试
使用功能分支
Git flow和Github flow及其问题
因为Git flow过于复杂,所以GitHub创建了一个更简单的替代方案GitHub flow。
GitHub flow是一个更简单的选择。
使用GitLab flow
GitHub flow仅具有功能分支和master分支。将所有内容合并到master分支中,并进行频繁部署意味着您可以将未发布的代码量减到最少,这与精化和持续交付的最佳实践是一致的。但是,这种流程仍然留下了许多有关部署,环境,发行版以及与issues集成的问题,这些问题尚未得到解答。使用GitLab flow,我们为这些问题提供额外的指导。
什么是GitLab工作流
## 什么是GitLab工作流
* 简化的分支策略
* 所有功能和修改首先转到master分支
* 允许”production”或”stable”分支
* Bug修复/热修复补丁是从master中挑选出来的
功能分支
## 功能分支
* 创建功能或错误修正分支以完成所有工作
* 使用合并请求合并到master分支
生产分支
## 生产分支
* 一个长期运行的生产发布分支,而不是单个稳定分支
* 考虑为每个要部署的版本创建一个标签
GitHub flow假设您每次合并功能分支都将其部署到生产环境。这对于SaaS应用程序是可能的,但是在许多情况下这是不可能的。一种情况是您无法控制发布的时间,例如,通过应用商店验证时发布的iOS应用程序。另一种情况是,当您有部署窗口时间(例如,上午10点到下午4点的工作日,工作团队处于满负荷状态时),但是您有时还会合并代码。在这些情况下,您可以创建一个反映已部署代码的生产分支。您可以通过合并master到生产分支,来部署新版本。如果您需要了解生产分支中使用的代码,则只需切换到生产分支即可查看。当在版本控制系统中,合并提交的大约时间很容易看出。如果您自动部署生产分支,那么这段时间非常准确。如果需要更精确的时间,可以让部署脚本在每个部署上创建一个标签。该flow流程可防止Git flow中出现的发布,标记和合并的开销。
GitLab flow环境分支
一个好主意是拥有一个自动更新到master分支的环境。仅在这种情况下,此环境的名称可能与分支名称不同。假设您有一个暂存环境,一个预生产环境和一个生产环境。在这种情况下,请将master分支部署到暂存。要部署到预生产,分支,请创建从master分支到预生产分支的合并请求。通过将预生产分支合并到生产分支来上线。此工作流仅在下游进行提交,可确保在所有环境中对所有内容进行测试。如果您需要通过修补程序挑选提交,通常是在功能分支上进行开发并在合并请求中将其合并到master。在这种情况下,请不要删除功能分支。如果master通过自动测试,然后将功能分支合并到其他分支。如果由于需要更多的手动测试而无法进行此操作,则可以将合并请求从功能分支发送到下游分支。
GitLab flow发布分支
## GitLab flow发布分支
* 如果您向客户发布软件,则很有用
* 准备新版本时,请从master创建稳定分支
* 考虑为每个版本创建标签
* 挑选关键bug修复到稳定分支,以发布补丁
* 永远不要将bug修复直接提交给稳定分支
仅当需要将软件发布到外界时,才需要使用发布分支。在这种情况下,每个分支都包含次要版本,例如2-3-stable,2-4-stable等。以master为起点创建稳定的分支,并尽可能晚地分支。这样,您可以将bug修复程序应用于多个分支的时间减至最少。宣布发布分支后,仅将严重的bug修复程序添加到分支。如果可能的话,请先将这些bug修复程序合并到master中,然后再将其修补到发布分支中。如果从合并到发行分支开始,您可能会忘记将它们修补到master中,然后在后续发行版中会遇到相同的bug。合并到master然后选择发布的方式称为“上游优先”策略,Google和Red Hat也采用这种策略。每次在发布分支中加入bug修复程序时,请通过设置新标签来增加补丁程序版本(以符合Semantic Versioning的要求)。一些项目还具有一个稳定的分支,该分支指向与最新发布分支相同的提交。在此流程中,通常不具有生产分支(或Git flow master分支)。
使用GitLab flow合并/拉取请求
合并或拉取请求在Git管理应用程序中创建。他们要求指定的人合并两个分支。GitHub和Bitbucket等工具选择名称“ pull request”,因为第一个手动操作是拉出功能分支。GitLab等工具选择名称“合并请求”,因为最后的动作是合并功能分支。在本文中,我们将它们称为合并请求。
如果您在功能分支上工作了几个小时以上,最好与团队的其他成员分享中间结果。为此,请创建一个合并请求,而不将其分配给任何人。而是在描述或评论中提及人们,例如“ / cc @mark @susan”表示合并请求尚未准备好进行合并,但是欢迎您提供反馈。您的团队成员可以对合并请求进行整体注释,也可以在特定的行上添加注释。合并请求用作代码审查工具,不需要单独的代码审查工具。如果审查发现缺点,那么任何人都可以提交并推动修复程序。通常,执行此操作的人是合并请求的创建者。当新的提交被推送到分支时,合并请求中的差异会自动更新。
准备好要合并功能分支时,请将合并请求分配给最了解您要更改的代码库的人员。另外,请提及您要反馈的其他任何人。在指定的人对结果感到满意之后,他们可以合并分支。如果指定的人不舒服,他们可以请求更多更改或关闭合并请求而不合并。
在GitLab中,通常会保护长期存在的分支,例如master分支,以使大多数开发人员无法修改它们。因此,如果要合并到受保护的分支,请将合并请求分配给具有维护者权限的人员。
合并功能分支后,应将其从源代码控制软件中删除。在GitLab中,可以在合并时执行此操作。删除完成的分支可确保分支列表仅显示正在进行的工作。它还可以确保如果有人重新打开问题,他们可以使用相同的分支名称而不会引起问题。
> 注意: 重新打开问题时,您需要创建一个新的合并请求。
使用GitLab flow进行问题跟踪
GitLab流是一种使代码与问题跟踪器之间的关系更加透明的方法。
对代码的任何重大更改都应从描述目标的问题开始。对于每次代码更改都有理由有助于通知团队其他成员,并使功能分支的范围保持较小。在GitLab中,对代码库的每次更改都以问题跟踪系统中的问题开始。如果还没有问题,请创建问题,只要更改需要大量的工作,即超过1小时。在许多组织中,提出问题是开发过程的一部分,因为它们用于sprint计划。问题标题应描述系统的期望状态。例如,问题标题“作为管理员,我要删除用户而不会收到错误”比“管理员无法删除用户”更好。
准备编写代码时,请从分支为该问题创建一个master分支。此分支是进行此更改相关工作的地方。
> 注意: 分支机构的名称可能由组织标准决定。例如,在GitLab中,GitLab EE中与GitLab CE中的分支等效的任何分支都必须以结尾-ee。
完成或要讨论代码后,请打开合并请求。合并请求是讨论更改并查看代码的在线位置。
如果您打开合并请求但未将其分配给任何人,则这是一个“进行中”合并请求。这些用于讨论建议的实现,但尚未准备好包含在master分支中。使用[WIP]或WIP:阻止合并请求的标题在准备好之前进行合并。
当您认为代码已准备就绪时,请将合并请求分配给审阅者。当他们认为代码已准备好包含在master分支中时,审阅者可以合并更改。当他们按下合并按钮时,GitLab将合并代码并创建一个合并提交,此事件稍后将很容易看到。合并请求始终会创建一个合并提交,即使分支可以不带一个就被合并。这种合并策略在Git中被称为“无快进”。合并后,删除功能分支,因为不再需要它。在GitLab中,合并时可以选择删除。
假设分支已合并,但是出现了问题,并且重新打开了该问题。在这种情况下,重用相同的分支名称没有问题,因为合并时第一个分支已删除。在任何时候,每个问题最多都有一个分支。一个功能分支有可能解决多个问题。
链接和关闭合并请求中的问题
## 链接和关闭合并请求中的问题
通过在提交消息或合并请求的描述中提及问题来链接到问题,例如,“ Fixes#16”或“ Duck type is优选”。请参见#12。” GitLab然后创建指向所提到问题的链接,并在问题中创建评论,并链接回合并请求。
要自动关闭链接的问题,请用“ fixes”或“ closes”一词来提及它们,例如,“ fixes#14”或“ closes#67”。当代码合并到默认分支时,GitLab会关闭这些问题。
如果您的问题跨越多个存储库,请为每个存储库创建一个问题,并将所有问题链接到父问题。
用rebase压缩提交
## 用rebase压缩提交
使用Git,您可以使用交互式rebase(rebase -i)将多个提交压缩为一个或重新排序。如果要用单个提交替换几个小的提交,或者想使订单更合逻辑,则此功能很有用。
但是,您永远都不应为已推送到远程服务器的提交提供基准。变基会为所有更改创建新的提交,这可能会引起混乱,因为同一更改将具有多个标识符。对于在同一分支上工作的任何人,这还会导致合并错误,因为他们的历史记录与您的历史记录不匹配。另外,如果有人已经检查过您的代码,则重新基准化将很难分辨自上次检查以来发生了什么变化。
您也应该永远不要使其他人创作的提交成为基准。这不仅会重写历史记录,还会丢失作者信息。重新定价可以防止其他作者被归属和共享部分内容git blame。
如果合并涉及许多提交,则撤消似乎更加困难。您可能会想通过在合并之前将所有更改压缩到一个提交中来解决此问题,但是如前所述,将已经推送的提交重新设置基础是一个坏主意。幸运的是,有一种简单的方法可以撤消其所有提交的合并。完成此操作的方法是还原合并提交。保留这种还原合并的能力是在--no-ff手动合并时始终使用“无快速转发”()策略的一个很好的理由。
> 注意: 如果先还原合并提交,然后改变主意,请还原还原提交以重做合并。Git不允许您再次合并代码。
减少功能分支中的合并提交
## 减少功能分支中的合并提交
进行大量合并提交会使您的存储库历史记录混乱。因此,您应该尝试避免在功能分支中合并提交。通常,人们通过在master分支上的提交之后仅使用rebase对提交进行重新排序来避免合并提交。使用rebase可以防止在合并master到功能分支时进行合并提交,并且可以创建整齐的线性历史记录。但是,如有关重新基准化一节中所述,您永远都不应对已推送到远程服务器的提交进行重新基准化。此限制使您无法重新评估已经与团队共享的进行中的工作,这是我们建议的做法。
重新定基还会产生更多工作,因为每次重新定基时,都必须解决类似的冲突。有时您可以重用记录的分辨率(rerere),但是合并起来更好,因为您只需解决一次冲突。Atlassian 在其博客上对合并和重新定标之间的权衡取舍做了更详尽的解释。
防止创建许多合并提交的一个好方法是不经常合并master到功能分支中。合并的原因有三个master:利用新代码,解决合并冲突以及更新长期运行的分支。
如果您需要利用master创建功能分支后引入的一些代码,通常可以通过选择提交来解决此问题。
如果功能分支存在合并冲突,则创建合并提交是解决此问题的一种标准方法。
> 注意: 有时您可以使用.gitattributes来减少合并冲突。例如,您可以将更改日志文件设置为使用联合合并驱动程序,以使多个新条目不会相互冲突。
创建合并提交的最后一个原因是使长时间运行的功能分支与项目的最新状态保持最新。这里的解决方案是使您的功能分支短暂存在。大多数功能分支的工作时间应少于一天。如果要素分支通常需要一天以上的工作,请尝试将要素拆分为较小的工作单元。
如果您需要将功能分支保持打开状态超过一天,则有一些策略可以使它保持最新状态。一种选择是master在一天开始时使用连续集成(CI)进行合并。另一个选择是仅从明确定义的时间点合并,例如,标记的发布。您还可以使用功能切换按钮隐藏不完整的功能,以便仍可以合并到master每一天。
> 注意:不要将自动分支测试与持续集成混为一谈。马丁·福勒(Martin Fowler)在有关要素分支的文章中做了以下区分:
>“我听说人们说他们正在做CI,因为他们每次提交时都在每个分支上运行构建(也许使用CI服务器)。那是持续不断的建设,是一件好事,但是没有集成,所以它不是CI。”
总之,您应该尝试防止合并提交,但不要消除它们。您的代码库应该是干净的,但是您的历史记录应该代表实际发生的情况。开发软件的过程非常麻烦,而且步履蹒跚,可以让您的历史反映这一点。您可以使用工具查看提交的网络图,并了解创建代码的混乱历史记录。如果您重新设置代码基础,则历史记录是不正确的,并且由于工具无法处理更改的提交标识符,因此无法补救。
经常投入并频繁推动
## 经常投入并频繁推动
使开发工作更轻松的另一种方法是经常提交。每次您拥有一组有效的测试和代码时,都应该提交。将工作分为单个提交,为开发人员稍后查看您的代码提供了上下文。较小的提交可以清楚地说明功能的开发方式,并且可以轻松地回滚到特定的时间点或还原一个代码更改而无需还原几个无关的更改。
经常投入也可以轻松地共享您的工作,这一点很重要,这样每个人都可以知道您的工作。即使功能分支尚未准备好进行审查,也应经常推送它。通过在功能分支或合并请求中共享您的工作,可以防止团队成员重复工作。在完成之前共享您的工作还可以进行有关更改的讨论和反馈,这可以帮助您在审查之前改进代码。
如何写一个好的提交信息
## 如何写一个好的提交信息
提交消息应该反映您的意图,而不仅仅是提交的内容。很容易看到提交中的更改,因此提交消息应说明您为什么进行这些更改。良好的提交消息的一个示例是:“组合模板以减少用户视图中的重复代码。”单词“更改”,“改进”,“修复”和“重构”不会在提交消息中添加太多信息。例如,将“改善XML生成”更好地写为“在XML生成中正确地转义特殊字符。
合并前进行测试
## 合并前进行测试
在旧的工作流程中,持续集成(CI)服务器通常master仅在分支上运行测试。开发人员必须确保其代码不会中断master分支。使用GitLab流时,开发人员从该master分支创建其分支,因此至关重要的是永不中断。因此,必须在接受每个合并请求之前对其进行测试。诸如Travis CI和GitLab CI之类的CI软件会在合并请求本身中显示构建结果,以简化此过程。
测试合并请求有一个缺点:CI服务器仅测试功能分支本身,而不测试合并结果。理想情况下,服务器还可以master在每次更改后测试分支。但是,对每个提交的重新测试在master计算上都是昂贵的,这意味着您更加频繁地等待测试结果。由于功能分支应该短暂存在,因此仅测试分支是可以接受的风险。如果新的提交master原因合并与功能分支冲突,请合并master回分支以使CI服务器重新运行测试。如前所述,如果您的功能分支经常持续几天以上,则应该缩小问题范围。
使用功能分支
## 使用功能分支
创建功能分支时,请始终从最新分支开始master。如果您在开始之前就知道您的工作依赖于另一个分支,则也可以从那里分支。如果您需要在启动后合并到另一个分支中,请在合并提交中说明原因。如果尚未将提交推送到共享位置,则还可以通过基于master或其他功能分支合并更改。如果您的代码可以正常工作并且不进行合并,则不要从上游再次合并。仅在需要时进行合并才能阻止在功能分支中创建合并提交,这些合并提交最终会破坏master历史记录。