GIT 工作流程:将大部分功能分支合并到 master 中,省略一个特定的提交?

Posted

技术标签:

【中文标题】GIT 工作流程:将大部分功能分支合并到 master 中,省略一个特定的提交?【英文标题】:GIT Workflow: Merge most of a feature branch into master, omitting one specific commit? 【发布时间】:2019-12-28 14:01:17 【问题描述】:

上下文:

两个独立的特性被提交到同一个分支。最旧的提交代表一个内聚特性(“特性 1”)。所有后续提交都代表第二个独立的内聚特征(“特征 2”)。

回想起来,这些应该是单独的功能分支,但它们都提交给同一个分支。

问题:

现在:发生了可预测的问题。要求开发人员将功能 2 合并到 Master,而不是功能 1。

他们做了什么:

#0 他们从 MASTER 分支,打算将分支用于功能 2 - 将他们的新分支称为“Feature_2”。

#1 他们忘记了他们所在的分支(功能 2),并在一次提交中为“功能 1”制作/测试/提交/推送大量文件更改。

#2、3、4 然后他们继续为功能 2 进行所有必要的更改,提交并推送到同一个分支。

现在 - 有人要求他们在没有功能 1(提交 #1)的情况下提交功能 2(提交 #2、#3、#4)。

#4 他们创建了一个新分支并将其命名为“BEFORE_REVERTING_#1”

#5 他们 Git Revert commit#1(通过 sourcetree 的“反向更改...”选项。)

#6 他们将 commit#5 合并到 master 中。

最终状态:

所以现在他们已经成功地将 #2,3,4 合并到 master 中,而无需使用 #1 中的代码。

问题:

现在或以后,我们如何将 Feature 1 / Commit #1 拉入 Master? (这样特征 1 和 2 都在 Master 中,并且历史在某种程度上是可破译的,如果不是完全精简的话)

我说得对吗,我们不能仅仅通过合并来做到这一点,因为 BEFORE_REVERTING_#1 只是指向稍后恢复的同一节点的指针,并且将被快速转发,并且需要使用其他一些 .git 功能?

如果您有幸了解 SourceTree 用户界面 - 有没有使用 SourceTree 的简单方法来做到这一点?

假设 #1-3 已经发生,开发人员应该做什么,而不是步骤 4/5 中的方法?

感谢您提供的任何帮助或澄清!

【问题讨论】:

【参考方案1】:

现在或以后,我们如何将 Feature 1 / Commit #1 拉入 Master?

Cherry pick它。本质上,这复制了提交。

git checkout master
git cherry-pick <commit id of feature 1>

假设 #1-3 已经发生,开发人员应该做什么,而不是步骤 4/5 中的方法?

还原提交很好。但他们也可以将功能分支分成两个分支。

你有这个。

A - B [master]
     \
      1A - 2A - 2B [feature]

你想要这个。

      2A - 2B [feature]
     /
A - B [master]
     \
      1A [feature1]

首先,在 1A 上粘贴一个新分支。

git branch feature1 1A

A - B [master]
     \
      1A [feature1]
        \
         2A - 2B [feature]

然后在 master 之上 rebase 2A 和 2B。

git rebase --onto master 1A 2B

      2A1 - 2B1 [feature]
     /
A - B [master]
     \
      1A [feature1]

你已经完成了。


对于更复杂的解开,使用interactive rebase 选择性地删除 提交。例如,如果您有...

A - B [master]
     \
      1A - 2A - 1B - 2B [feature]

而你想要...

      2A - 2B [feature]
     /
A - B [master]
     \
      1A - 1B [feature1]

feature 建立一个新分支。

git checkout feature
git branch feature1

A - B [master]
     \
      1A - 2A - 1B - 2B [feature]
                        [feature1]

然后对它们中的每一个进行交互式变基。删除有问题的提交。从 feature 删除 1A 和 1B。从 feature1 删除 2A 和 2B。

git checkout feature
git rebase -i master
# delete 1A and 1B

      2A - 2B [feature]
     /
A - B [master]
     \
      1A - 2A - 1B - 2B [feature1]
git checkout feature1
git rebase -i master
# delete 2A and 2B

      2A - 2B [feature]
     /
A - B [master]
     \
      1A - 1B [feature1]

【讨论】:

【参考方案2】:

摘樱桃(根据 Schwern 的回答)可能是最简单的解决方案;但请考虑您的团队/项目的分支策略。您可能希望选择新的 feature 1 分支并将其合并到 master 中,而不是直接选择到 master 中。

还有多种其他方法可以复制由于还原而从master(或其他分支)中排除的提交,具体取决于具体情况。如果整个分支已被排除(因为它已合并并且合并已恢复),检查分支和rebase -f 通常是有意义的。主要区别在于,如果您这样做,您将使用新提交重写分支历史记录(除非您专门使用不这样做的过程);在挽救整个分支的情况下,这可能是您想要的,但您需要了解如果分支已共享,则重写该分支的含义。

我不同意另一个答案的地方是,开发人员所做的可能或可能不会“很好”。这取决于您的团队关于如何使用 git 的协议。这可能看起来很挑剔,但我真的厌倦了 slashdot 上的“专家”告诉团队他们的工作协议应该是什么样子,只是因为这是他们习惯做事的方式。

一般来说,开发者有两个选择:他们可以从feature 2 分支恢复提交——他们可能是最直接的变体——代价是必须稍后复制恢复的提交并拥有“奇怪”的历史记录.或者他们可以重写历史以分离分支,但代价可能是对所有开发人员进行一些分支清理,因为这意味着重写已经共享的分支的历史(参见git rebase 文档,他们在其中谈论“上游变基")

【讨论】:

以上是关于GIT 工作流程:将大部分功能分支合并到 master 中,省略一个特定的提交?的主要内容,如果未能解决你的问题,请参考以下文章

Git:如何使用 VS Code 源代码控制将功能分支合并到主分支?

GIT(实验室)。在合并请求中从一个分支创建分支

git 怎么提交合并分支的部分代码

Git:无法将功能分支合并到当前分支

使用 Git 将 master 的更改合并到所有分支中?

我如何合并从dev到开始然后生产的git分支