git-flow 的问题
我到处旅行,向人们教授 Git,几乎我最近完成的每堂课和研讨会都问我对git-flow 的看法。我总是回答说我认为它很棒——它采用了一个系统 (Git),它拥有一百万个可能的工作流,并记录了一个经过充分测试的、灵活的工作流,该工作流以相当简单的方式适用于许多开发人员。它已成为某种标准,因此开发人员可以在项目或公司之间移动并熟悉此标准化工作流程。
然而,它确实有它的问题。我从人们那里听到了一些意见,他们不喜欢新功能分支的开始develop
而不是master
,或者它处理修补程序的方式,但这些都相当小。
对我来说更大的问题之一是它比我认为大多数开发人员和开发团队实际需要的更复杂。它足够复杂,以至于开发了一个大的帮助脚本来帮助执行流程。虽然这很酷,但问题是它不能在 Git GUI 中强制执行,只能在命令行上执行,因此唯一必须真正很好地学习复杂工作流程的人,因为他们必须手动完成所有步骤,是那些对系统不够满意而无法从命令行使用它的人。这可能是一个巨大的问题。
这两个问题都可以通过更简化的过程轻松解决。在 GitHub,我们不使用 git-flow。我们使用,并且一直使用,一个更简单的 Git 工作流程。
它的简单性赋予了它许多优点。一是人们很容易理解,这意味着他们可以快速掌握它,而且他们很少搞砸或不得不撤消他们做错的步骤。另一个是我们不需要包装脚本来帮助执行或遵循它,因此使用 GUI 等不是问题。
GitHub 流程
那么,我们为什么不在 GitHub 上使用 git-flow 呢?嗯,主要问题是我们一直在部署。git-flow 过程主要围绕“发布”而设计。我们并没有真正的“发布”,因为我们每天都部署到生产环境中——通常一天几次。我们可以通过我们的聊天室机器人来做到这一点,它与我们的 CI 结果显示在同一个地方。我们努力使测试和运输过程尽可能简单,以便每位员工都能轻松完成。
定期部署有很多好处。如果每隔几个小时部署一次,几乎不可能引入大量的大 bug。可以引入小问题,但随后可以非常快速地修复和重新部署它们。通常,您必须执行“修补程序”或正常流程之外的其他操作,但这只是我们正常流程的一部分 - 修补程序和非常小的功能在 GitHub 流程中没有区别。
一直部署的另一个优势是能够快速解决各种问题。我们可以对引起我们注意的安全问题做出响应,或者以难以置信的速度实现小而有趣的功能请求,但我们可以使用与处理正常甚至大型功能开发完全相同的流程来解决这些更改。这都是相同的过程,而且都非常简单。
我们如何做
那么,什么是 GitHub Flow?
master
分支中的任何东西都是可部署的- 要在一些新的工作,创建一个名为描述性分支出来的
master
(即:new-oauth2-scopes
) - 在本地提交到该分支并定期将您的工作推送到服务器上的同名分支
- 当您需要反馈或帮助,或者您认为分支已准备好合并时,请打开拉取请求
- 在其他人审查并签署该功能后,您可以将其合并到 master
- 一旦合并并推送到“master”,您就可以并且应该立即部署
这就是整个流程。它非常简单、非常有效并且适用于相当大的团队——GitHub 现在有 35 名员工,其中可能有 15-20 人同时在同一个项目 (github.com) 上工作。我认为大多数开发团队 - 同时处理相同逻辑代码的团队可能会产生冲突 - 大约在这个规模或更小。特别是那些进步到足以进行快速和一致部署的人。
因此,让我们依次查看这些步骤中的每一个。
#1 - master 分支中的任何东西都是可部署的
这基本上是系统唯一的硬性规则。只有一个分支具有任何特定且一致的含义,我们将其命名为master
。对我们来说,这意味着它已经部署,或者在最坏的情况下将在数小时内部署。这种情况非常罕见(分支被移回较旧的提交以恢复工作) - 如果出现问题,提交将被恢复或将引入新的提交来解决问题,但分支本身几乎从不回滚。
该master
分支是稳定的,这是永远,永远安全地从它部署或创建关闭它新的分支机构。如果你将一些未经测试的东西推送给掌握或破坏了构建,你就破坏了开发团队的社会契约,你通常会对此感到非常糟糕。我们推送的每个分支都有测试运行并报告到聊天室,所以如果你没有在本地运行它们,你可以简单地推送到服务器上的主题分支(甚至是一个提交的分支)并等待Jenkins告诉你它是否通过了一切。
您可以拥有一个deployed
仅在部署时更新的分支,但我们不会这样做。curl
如果我们需要进行比较,我们只需通过 webapp 本身公开当前部署的 SHA 。
#2 - 从 master 创建描述性分支
当您想开始处理任何事情时,您可以在稳定master
分支之外创建一个具有描述性命名的分支。现在 GitHub 代码库中的一些示例是user-content-cache-key
,submodules-init-task
或redis2-transition
。这有几个优点——一个是当你获取时,你可以看到其他人一直在研究的主题。另一个原因是,如果您暂时放弃某个分支并稍后再返回到它,则很容易记住它是什么。
这很好,因为当我们转到 GitHub 分支列表页面时,我们可以很容易地看到最近进行了哪些分支以及它们在这些分支上的大致工作量。
它几乎就像一个即将推出的功能列表,当前状态大致如此。如果您不使用此页面,则该页面很棒 - 它只向您显示相对于您当前选择的分支具有独特工作的分支,并对其进行排序,以便最近工作的分支位于顶部。如果我真的很好奇,我可以单击“比较”按钮以查看该分支独有的实际统一差异和提交列表。
因此,在撰写本文时,我们的存储库中有 44 个分支,其中有未合并的工作,但我也可以看到,上周只有大约 9 或 10 个分支被推送到了。
#3 - 不断推送到命名分支
与 git-flow 的另一个很大区别是我们不断推送到服务器上的命名分支。由于我们唯一真正需要担心的是master
从部署的角度来看,推送到服务器不会把任何人搞砸或混淆——所有不是master
的只是正在处理的东西。
它还确保我们的工作始终得到备份,以防笔记本电脑丢失或硬盘驱动器故障。更重要的是,它让每个人都保持不断的沟通。一个简单的 'git fetch' 基本上会给你一个 TODO 列表,列出每个人当前正在做的事情。
$ git fetch
remote: Counting objects: 3032, done.
remote: Compressing objects: 100% (947/947), done.
remote: Total 2672 (delta 1993), reused 2328 (delta 1689)
Receiving objects: 100% (2672/2672), 16.45 MiB | 1.04 MiB/s, done.
Resolving deltas: 100% (1993/1993), completed with 213 local objects.
From github.com:github/github
* [new branch] charlock-linguist -> origin/charlock-linguist
* [new branch] enterprise-non-config -> origin/enterprise-non-config
* [new branch] fi-signup -> origin/fi-signup
2647a42..4d6d2c2 git-http-server -> origin/git-http-server
* [new branch] knyle-style-commits -> origin/knyle-style-commits
157d2b0..d33e00d master -> origin/master
* [new branch] menu-behavior-act-i -> origin/menu-behavior-act-i
ea1c5e2..dfd315a no-inline-js-config -> origin/no-inline-js-config
* [new branch] svg-tests -> origin/svg-tests
87bb870..9da23f3 view-modes -> origin/view-modes
* [new branch] wild-renaming -> origin/wild-renaming
它还可以让每个人通过查看 GitHub 分支列表页面看到其他人都在做什么,这样他们就可以检查他们,看看他们是否想要帮助做某事。
#4 - 随时打开拉取请求
GitHub 有一个很棒的代码审查系统,叫做Pull Requests,我担心没有足够的人知道。许多人将它用于开源工作 - fork 项目、更新项目、向维护者发送拉取请求。但是,它也可以轻松用作内部代码审查系统,这就是我们所做的。
实际上,我们更多地将它用作分支对话视图而不是拉取请求。您可以在 GitHub 的单个项目(公共或私有)中将拉取请求从一个分支发送到另一个分支,因此除了“请合并”之外,您还可以使用它们说“我需要帮助或审查”。
在这里,您可以看到 Josh cc'ing Brian 进行审查,Brian 就其中一行代码提出了一些建议。再往下,我们可以看到 Josh 承认了 Brian 的担忧,并推出了更多代码来解决这些问题。
最后你可以看到我们仍处于试用阶段——这还不是一个部署就绪的分支,在我们真正想要将它合并到master
部署之前很久,我们使用拉取请求来审查代码。
如果您被困在您的功能或分支的进度中并需要帮助或建议,或者如果您是开发人员并且需要设计师来审查您的工作(反之亦然),或者即使您只有很少或没有代码但有一些截图comps 或一般想法,您打开一个拉取请求。您可以通过添加@username来抄送 GitHub 系统中的人员,因此如果您想要特定人员的评论或反馈,只需在公关消息中抄送他们(正如您在上面看到的 Josh 所做的那样)。
这很酷,因为拉取请求功能让您可以对统一差异中的单个行、单个提交或拉取请求本身进行评论,并将所有内容内联到单个对话视图中。它还可以让你继续推送到分支,所以如果有人评论说你忘记做某事或者代码中有错误,你可以修复它并推送到分支,GitHub 会在对话视图中显示新的提交你可以在这样的分支上继续迭代。
如果分支开放时间过长,你觉得它与 master 分支不同步,你可以将 master 合并到你的主题分支并继续。您可以在拉取请求讨论或提交列表中轻松查看分支上次与“master”保持同步的时间。
当所有事情都在分支上真正完成并且您觉得它已准备好部署时,您可以继续下一步。
#5 - 仅在拉取请求审查后合并
我们不会简单地直接在master
主题分支上工作或在主题分支上工作并在我们认为完成时将其合并 - 我们试图从公司中的其他人那里获得批准。这通常是 +1 或表情符号或“ ”评论,但我们会尝试让其他人查看。
一旦我们得到了,并且分支通过了 CI,我们就可以将其合并到 master 中进行部署,当我们推送它时,它会自动关闭 Pull Request。
#6 - 审核后立即部署
最后,您的工作完成并合并到master
分支中。这意味着即使你现在不部署它,人们也会基于它进行新的工作,而下一次部署(可能会在几个小时内发生)会将它推出。因此,由于您真的不希望其他人推动您编写的破坏事物的东西,因此人们倾向于确保它在合并时确实稳定,并且人们也倾向于推动自己的更改。
我们的篝火机器人hubot可以为任何员工进行部署,所以很简单:
hubot depoy github to production
将部署代码和零停机时间重新启动所有必要的进程。你可以在 GitHub 上看到这有多常见:
您可以看到 6 个不同的人(包括支持人员和设计师)在一天内部署了大约 24 次。
我已经为一个包含一行更改的提交的分支完成了这项工作。该过程简单、直接、可扩展且功能强大。您可以使用功能分支来完成,其中 50 次提交耗时 2 周,或者 1 次提交耗时 10 分钟。这是一个如此简单和无摩擦的过程,您不会因为即使提交 1 次而不得不这样做而感到恼火,这意味着人们很少尝试跳过或绕过该过程,除非更改非常小或微不足道以至于无关紧要.
这是一个非常简单而强大的过程。我想大多数人都会同意 GitHub 有一个非常稳定的平台,如果出现问题就会很快得到解决,并且新功能的引入速度很快。质量或稳定性没有任何妥协,因此我们可以获得更高的速度或简单性或更少的过程。
结论
Git 本身理解起来相当复杂,让你使用它的工作流程比必要的更复杂,只会给每个人的一天增加更多的精神开销。我总是提倡使用最简单的系统,它可以为您的团队工作,直到它不再工作为止,然后仅在绝对需要时才增加复杂性。
对于必须在更长的时间间隔内(发布之间的几周到几个月)进行正式发布,并且能够进行热修复和维护分支以及很少因发布而产生的其他事情的团队,git-flow使得感觉,我会极力提倡它的使用。
对于已经建立了交付文化、每天推向生产、不断测试和部署的团队,我建议选择更简单的东西,比如 GitHub Flow。
via http://githubflow.github.io/
最后更新于 2022年6月26日