Git工作流程:重新设置已发布/共享分支

45

我们团队已经热衷于采用rebase工作流,但我们可能有些过度,这就是这个问题的核心:你来评判。

现在使用pull --rebase对我来说已经是轻而易举的事情了。然而,我们还有大型的功能分支供多人共同开发。定期地,我们想要引入正在master分支上发生的更改。传统智慧会让我们合并,因为它是一个共享分支。然而,在我们迷恋rebase的过程中,我们决定对这些分支进行rebase。当然,这需要大家的配合。工作流程大概是这样的:

1)重新定位者与每个人协调,确保他们都在功能分支上检入并推送,然后要求他们在得到全部清除之前不再在该分支上进行任何工作。

2)重新定位者将功能分支rebase到master上,删除远程功能分支(git push origin: feature),然后推送新的、rebase过的功能分支(git push origin feature)

3)重新定位者让每个人获取最新状态,这将更新他们的功能分支,然后删除本地功能分支(git branch -D feature),创建一个新的本地功能分支来跟踪远程功能分支。然后每个人都可以得到全部清除。

这个工作流程有效,部分原因是我们是一个小组,工作中断很少。然而,我担心我们正在学习不良的Git习惯(在共享分支上进行rebase),或者这个工作流程将不能很好地扩展。

好处是,我们的代码库历史记录非常美妙。

Git大师们,你们认为我们是在玩火,还是采用了合理的工作流程?

更新:

自从我最初提出这个问题以来已经过去了两年,我们的工作流程已经发生了变化。我们仍然经常使用git pull --rebase,所以这一点没有改变。这是常识,并且可以防止所有难看、混乱的小合并。 (我们保持基本同步,所以git pull --rebase的代价很小)。

除此之外,偶尔英雄式地纠正错误,我们已经走出了变基的疯狂。 大多数情况下合并是有意义的。 然而,肆意合并是有问题的,并且确实导致了我两年前担心的混乱、混乱的历史。

我们的解决方案有几个组成部分:

  • 主分支是"原始的"。 主题分支被合并进去后,一旦它们这样做,主题分支就被废弃了。 换句话说,将主题分支合并表示该工作已准备好投入生产,并且现在是主分支的一部分。 查看我们的版本历史记录,非常清楚正在发生什么:将主题分支合并到主分支中,就是这样。

  • 必要时我们使用一次性集成分支。 例如,如果我们有主题分支A、B和C,它们都没有准备好集成到主分支中,但我们需要测试它们在一起,我们只需创建一个QA分支(通常是从主分支开始),然后将A、B和C合并在一起。 在某些时候,QA分支会被删除或重新使用。 关键是它不打算以任何方式永久存在,并且它没有与主分支相同的限制(您可以随时将主题分支合并几次)。 如果历史记录变得太混乱,您可以只删除QA分支并重新开始(这是我们发现非常自然的方法)。

  • 在合并时,始终使用git merge --no-ff。 这是从两年前我们"线性提交历史"的痴迷中做出的如此巨大的逆转,值得一提。 现在我们已经放松了对线性提交历史的痴迷,并认识到合并是好的、有用的,我们已经开始依赖于主题分支是实际分支而不仅仅是最终与主分支合并的一系列提交。 git merge --no-ff确保总是有一个合并提交,即使没有必要。

  • 我们对提交信息和分支有一个通用的约定,并且更重要的是,它与我们的问题跟踪系统进行了交叉引用。我们的问题跟踪系统使用数字问题编号,对于任何功能(或缺陷),我们都有一个问题编号(例如1234)。如果你正在处理这个问题,你将创建一个名为_1234 的分支,并在每个提交信息的开头使用"_1234: doing blah blah"。这可能看起来有点过于琐碎,但它确实为我们工作得很好,显著地减少/消除了混乱。

  • 使用git封装器来鼓励工作流程的吻合。这是我们目前正在努力的事情,但我们意识到这完全是必要的,以防止简单易懂的错误,例如从错误的地方创建分支(最近我们在一次灾难中,开发人员从一次性QA分支创建了一个主题分支:该主题分支已被批准上线,它被合并了...而不是被批准上线的一堆变更也进入了项目中)。我们的git封装器将要求确认,每当您做一些不寻常的事情(例如创建一个不是基于master的分支,创建一个名称不是_NNNN的分支,提交信息不以_NNNN开头等)。偶尔,我们确实需要做这些事情,因此封装器并不会阻止它,但它确实可以防止人们意外地做一些不该做的事情。


  • 4
    我认为这太过了。如果你的特性分支存在时间很长,你应该进行合并操作。否则,你会发现从主分支到特性分支最新提交之间的所有历史提交都没有经过测试。此外,你的提交历史也会变得不太真实。 - Andrew Marshall
    2
    嗯,使用 git 包装器来鼓励工作流程的一致性是关键。基本上你不再使用 git,而是使用你的包装器。 - Alexander Gorshenev
    1
    嗨,你的1到3步骤与我的想法完全一致,但为了明确事情,你目前还使用这三个步骤吗?我担心会误解你的新编辑中的任何内容。 - Marson Mao
    2
    嗨,马森,我们现在很少再使用1-3了。我们的rebase狂潮已经结束了。我们已经意识到,追求线性提交历史的教条主义是错误的。我们仍然喜欢git pull --rebase,并通过rebase来纠正工作流问题,但大多数情况下我们会合并分支。 - Ethan Brown
    1个回答

    27

    听起来这似乎过于复杂,而且不会很好地扩展。更简单的方法可能是定期将 master 分支合并到您的特性分支中,然后在合并回 master 分支时,做变基(以删除中间不必要的合并),并使用 --no-ff 选项合并回 master 分支(以产生一个合并提交)。这只需要一个人处理变基,而且他们不需要进行任何协调,因为没有其他人需要强制更新任何内容(因为分支在合并后将被删除,而不是保留在重写状态下)。您还可以决定跳过变基,只需保留中间合并即可,这样可以更准确地反映您的开发工作流程,并消除产生实际上无法构建的提交的风险。


    1
    在这种情况下,合并主分支到功能分支时解决的任何冲突是否必须在重新基于时再次解决?(相反,如果您不预期合并冲突,我认为这是一个非常便捷的工作流程) - rethab
    1
    如果你打开rerere(查看git help rerere),它可以自动解决它们,具体取决于它是否可以正确识别冲突并将其解决为过去曾经解决过的冲突。 - Lily Ballard
    为什么你说要删除中间的“不必要”的合并呢?从主分支合并可能需要使用一些新的API等。我认为答案中应该删除“不必要”这个词。 - cryptickey

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接