在 Git 中使用基于主干和基于功能的工作流有哪些优缺点?

What are the pros and cons of using a trunk-based Vs feature-based workflow in Git?

我非常喜欢Git中基于特性的工作流的想法:使用特性分支来支持并行开发。

在基于特性的工作流程中,我会在特性分支(非 master)中开发我的任务,并且我会经常从 master 变基以避免潜在的冲突。如果协作,我将 push/pull 功能分支到远程。 当准备好集成到 master 时,我从我的功能分支打开一个 pull-request 到 master,这样 pull-requests 就会被同行审查并自动评估以了解 pull-request(我的功能分支合并到 master)通过构建和单元测试。如果 pull-request 是 "green" 那么我的功能分支会自动合并到 master。

我觉得上述工作流程很好。然而,在某些互联网帖子中,他们提倡 "trunk-based development"(例如 1, 2)。

在我看来,trunk-based development不鼓励开发成单独的feature branches,而是所有的开发者都开发成master。该模型鼓励开发人员每天(Martin Fowler 的 CI 实践)集成到 master 以避免冲突(相比之下,我要做的是将我的功能分支重新设置为 master)。

我想知道这个模型在基于特征的模型上有哪些优势。我对基于主干的模型有几个疑问:

  1. 如何进行代码审查?在基于特征的模型中很容易:进入特征分支。在trunk-based模型中,既然所有的commit都发布在master中,那么如何让它们被review呢?事实上,如果我在合并到 master 时解决冲突,这个提交不会看起来像被审查(我不喜欢那样)吗?

  2. 两个开发人员如何协作开发同一功能?在里面 基于特征的模型,两者都可以在特征分支上工作。在里面 基于主干的模型,所有开发人员将在“所有 功能”(不知何故)。对吗?

  3. 我相信,基于主干的模型 "created" 避免了长期存在的功能分支在合并到主线时成为潜在冲突地狱的问题。但是,如果功能分支的生命周期很短,并且经常从主线重新建立基线,那么问题是什么?

  4. 总的来说,与主干相比,主干为主有哪些好处? 基于特征的工作流程?

谢谢 :-)

您的参考 1 already discuss some points about code-review. This answer is primarily based on my experience at work with the Gerrit 工具和 trunk-based 工作流程。

  1. How would code-review be done? In feature-based model is easy: into the feature branch. In the trunk-based model, since all the commits are published in master, how can I make them reviewed? In fact, if I resolve conflicts when merging into master, wouldn't this commits appear as to be reviewed (i wouldn't like that)?

trunk-based 工作流程中的 code-review 理想情况下应该在提交集成到 master 之前完成。手动地,开发人员会将他们的提交推送到某个临时功能分支,并在获得批准后将这些提交重新设置为 master 并推送它们(可选择将它们压缩为单个提交)。

Gerrit 自动执行此过程。将提交推送到 Gerrit 时,它会创建一组(几乎不可见的)临时分支来审查提交。在审查期间,所做的任何更正都会修改到正在审查的提交中,并再次推送给 Gerrit。一旦获得批准,提交将自动集成到 master 中(用户可以在 rebase、cherry-pick 和 merge 等选项中选择如何集成)。

Gerrit 最适用于 trunk-based 工作流程中的 code-review,因为它促进审查 commit-by-commit 并且推送的提交仅在通过审查后出现在 master 中(更正作为修正完成,所以 "wrong" 提交永远不会进入 master)。

  1. How would two developers collaborate on the same feature? In the feature-based model, both would work on the feature branch. In the trunk-based model, all developers would be collaborating in "all the features" (somehow). Right?

没错。由于所有功能都在同一分支中开发,因此所有开发人员都在同一分支上提交。代码审查(和持续集成)会给这个分支总是足够稳定的信心(至少对于开发,如果不是生产)。

缺点是不同复杂功能的提交在日志中变得交错 - 添加一些问题跟踪系统的数量有很大帮助。然而,在 code-review 之后压缩提交,或者使用 Gerrit(它强制 reivew commit-by-commit,而不是 branch-by-branch),经验表明大多数功能只是单个提交(相当于合并提交在 feature-based 工作流程中)。

  1. I believe, the trunk based model was "created" to avoid the problem of long-lived feature branches are their potential conflict hell when merging it to the mainline. However, if feature branches are short-lived, and if they are often rebased from the mainline, what is the issue then?

问题出在一些 long-lived 功能分支被集成到 master 中时。然后,每隔 long-lived 个功能分支都必须一次集成该已完成功能的所有更改。如果 finished 和 rebasing 功能分支都进行了一些重构,那就更糟了。

  1. Overall, which benefits can carry the trunk-based compared to the feature-based workflow?

我看到的最大的好处是:

  • 更线性的历史,更容易理解和制作 cherry-pick 和恢复。
  • 较小的冲突解决方案,主要是在重大重构的情况下。

但是,我想再次推荐使用 Gerrit(或一些类似的工具)在 trunk-based 工作流程中自动化 code-review 流程,而不是使用专为审查 pull-requests 而设计的工具(feature-based 工作流程)。

和您一样,Debitoor 的开发人员对基于主干的开发有一些疑问。为了克服这些问题,他们想出了一个创新的解决方案,他们称之为 Koritsu。

Kōritsu 是日语中效率的意思,这种方法旨在确保开发人员永远不会打扰或阻止彼此。 Koritsu 与短暂的功能分支非常相似,除了它让功能分支可以存活长达一周,并自动将每个合并部署到主干。

Debitoor 多年来一直在使用 Koritsu 进行我们的网站和移动开发。对我们来说,一直 运行 顺利,没有任何问题。有一件事是肯定的:我们不会回到基于主干的开发

我们的 CTO Allan 写了一篇关于 the problems with Trunk Based Development 以及 Koristu 是如何设计来修复它们的文章。这篇文章还包括一段视频,其中包含他关于基于主干开发的创新解决方案的演讲视频,其中更详细地解释了一切。