首先,请注意:如果您坚持此工作流程并解决当前问题,您将面临其他更微妙的问题。像这样的工作流试图在开发生命周期的多个阶段返回到单个功能分支的合并,但会遇到麻烦,因为它们忽略了不同分支上的更改之间可能存在的交互。
话虽如此,让我们专注于您的一些问题。您的场景(带插图)如下所示:
首先,您有 _dev 和 _qa 分支。 (其他的,为了简单起见,我们暂时搁置。)
A -- B -- C <--(_dev)(_qa)
我假设我们开始的状态是 _dev 中的所有内容都已通过 _qa(当然所有已通过 _qa 的内容都应在 _dev 中),所以他们指向相同的提交。这可能会遗漏一些会阻碍您的工作流程的复杂因素,但它仍然足以让我们了解您当前面临的问题。现在
Dev1 创建 feature1
A -- B -- C <--(_dev)(_qa)
\
D -- E <--(feature1)
Dev1 将 feature1 合并到 _dev(假设此时它正在等待代码审查)
(_qa)
|
A -- B -- C ------ M1<--(_dev)
\ /
D -- E <--(feature1)
Dev1 创建并开始处理 feature2
(_qa) F -- G <--(feature2)
| /
A -- B -- C ------ M1<--(_dev)
\ /
D -- E <--(feature1)
Dev1 将 feature2 合并到 _dev 并通过代码审查。
(_qa) F -- G <--(feature2)
| / \
A -- B -- C ------ M1 ------ M2 <--(_dev)
\ /
D -- E <--(feature1)
Dev1 尝试将 feature2 合并到 _qa
好的,那么这里会发生什么?好吧,feature2 是_qa 的后代(因为我们从_qa 和_dev 在同一个地方开始)。因此,您可以将_qa 快进到feature2(即使您不这样做,生成的合并提交也将具有与您拥有的内容相同的内容)。但是feature2植根于M1; feature1 的更改可从 feature2 访问,但无法从 _qa 访问,因此合并将包括它们。
如果我们从_dev 可访问_qa 开始(而不是两个指向同一个提交),则完全相同的分析将成立。如果出于某种原因,_qa 包含更改不可从_dev 访问,我们可以有类似的东西
Q <--(_qa) F -- G <--(feature2)
/ / \
A -- B -- C ------ M1 ------ M2 <--(_dev)
\ /
D -- E <--(feature1)
在这种情况下,git 会在 _qa 和 feature2 之间找到一个合并基础——即一个共同的祖先。那将是B。然后它将“B 和 _qa 之间的更改”与“B 和 feature2 之间的更改结合起来。同样,B 和 feature2 之间的更改包括 @ 所做的更改987654357@ 因为feature2 植根于M1(即feature1 被合并后的一个点)。
在所有情况下,要点都是相同的:在大多数情况下(包括在合并期间),git 不会将提交(或它们之间的增量)视为“属于”这个分支或那个分支。相反,它关心是否在合并基础的路径上发生了更改。
通常可以让 git 单独查看“来自分支”的更改的一种情况是 rebase。但是,您的工作流程需要大修才能利用这一点,并且会导致其他并发症。这不是我在这里推荐的路径。
另一种看起来可以修补工作流程的方法是要求开发人员在 _dev 和 _qa 之间的合并基础上启动新功能分支。 但是这可能只会把罐子踢下去(除非更改在达到_qa 后将始终“保持秩序”,这不是一个合理的假设 - 特别是如果 QA 发现了缺陷)。此外,这增加了为一个功能完成的工作与为下一个功能完成的工作之间的隔离,最终意味着您可能需要处理更多的合并冲突。
无论如何,我认为这解决了您的为什么问题。至于什么:
好吧,虽然您使用“git flow”作为“分支和合并策略”的通用术语,但实际上 git flow 是特定分支和合并策略的名称。我建议阅读它。您列出的需求并非独一无二,甚至不常见,因此与其认为您必须自定义此流程以满足这些需求,不如研究人们如何使用此流程满足这些需求。