Git 合并 Fast-Forward 和 Git 变基

21

快进的 git mergegit rebase 有什么区别?两者都能保持线性历史并避免合并提交,为什么要使用其中之一呢?如果不能这样做,那么我认为是真的,我看不到的整个故事是什么?

谢谢!


1
它们完全不同。 - matt
合并(在一般情况下)会产生分支合并历史。作为特殊情况,Git 所谓的快进式合并(实际上不是合并)则不会产生。因为这就是你所询问的——快进式合并——它们最终会做同样的事情。 - torek
@torek,所以快进和变基是一样的吗? - Newo
不是一般情况,但对于这个特定案例是的。 - torek
啊,好的。是时候了解一下快进的相关知识了。 - Newo
2个回答

43

当您领先于主要分支时,两者都执行相同的操作。

如果您既在主要分支的前面又在后面,则无法进行快速向前合并,因为主要分支上有更新的提交。但在这种情况下,您可以使用 rebase,基于领先于主要分支的提交创建新的提交。

当您领先于主要分支时:

            *E-*F-*G-*H-*I    BRANCH
           /
*A-*B-*C-*D                   MAIN

当你进行快速合并时,主指针将向前移动到分支的末端。当你进行变基操作时,分支中的每个提交都会被移动到主线的头部之后。最终结果是相同的:

*A-*B-*C-*D-*E-*F-*G-*H-*I MAIN | BRANCH

当你领先或落后于MAIN时:

            *E-*F-*G-*H-*I    BRANCH
           /
*A-*B-*C-*D-*J-*K             MAIN

如果J..K挡住了,你就不能将E..I快速合并到主分支中。所以在这种情况下,无法进行快速合并。

但是你可以将E..I变基到K:

*A-*B-*C-*D-*J-*K-*E'-*F'-*G'-*H'-*I'             MAIN | BRANCH

但是实际发生的是新的提交包含了E的更改并添加到主分支中,然后新的提交包含F的更改并添加到主分支中......等等,直到所有来自该分支的提交都被“移动”/“重放”到另一个分支上。 结果再次是一条单一的历史线,没有分支和合并。

由于提交必须重新应用并可能解决冲突,因此实际提交将更改,生成新的提交ID等。


4

是的,快进是一种在不合并提交的情况下维护线性历史记录的方式。

快进的 git 合并和 git 变基有什么区别?

当使用 git 进行快进时,无论你使用的是 git 合并还是 git 变基,都是相同的。
然而,使用 git 合并来合并两个分支,并不总是快进。在这种情况下,你可以使用 git 变基来准备合并分支的提交历史,以实现快进合并。

在使用 git 合并时何时可以进行快进

让我们假设一个场景:你正在自己的项目上工作。在某个地方,你想要添加一个你考虑过的功能。这个功能有一定挑战性,你需要在一个单独的分支上完成它以查看是否能够构建它。

您的项目有一个名为develop的主分支。为了构建这个功能,您创建了一个名为feature的分支并切换到它。您在这个功能上进行工作并进行了多个提交。经过一段时间的努力,您终于成功构建了它。
此时,您的项目历史如下:

evolved history of feature branch

实际上,自从你转到在“feature”分支进行构建和提交以来,“develop”分支没有新的提交。因此,没有分歧的工作,即“feature”分支直接领先于“develop”。当我们使用以下方法将“feature”合并到“develop”中时:
git checkout develop
git merge feature

我们将进行快速合并。这意味着,Git不会生成一个合并提交,而只是将`develop`分支指向`feature`分支的最新提交点。

fast forward merge

使用git rebase进行Git快进合并
在第二种情况下:您需要为项目构建更多功能。您引入了更多的开发人员,并让他们在各自的功能/主题分支上构建功能。而您自己正在feature-2分支上构建另一个功能。
在某个时刻,您完成了自己的功能。但此时,您指派给其他开发人员构建功能的工作已经完成,并且已将其合并到develop分支中:

Feature branch before rebase

现在如果你合并像这样:
git checkout develop
git merge feature-2

你无法进行快进合并,因为自从你上次分支以来,develop分支已经有了更新的提交。要使快进合并成为可能,你需要将feature-2分支的基础改为develop分支上的最新提交,例如:
git rebase develop feature-2 #checkout feature-2 then rebase

这就是现在的历史:

Feature branch after rebase

关于git rebase的一些内容是它会改变分支的基础,并按照它们发生的顺序重新应用其提交,使用新的ID。因此,在图像中被表示为c3'...c5'的提交。
一旦我们对feature-2分支进行了rebase,我们现在可以将其合并到develop分支中。
git checkout develop
git merge feature-2

结果应该是一个快进。将feature-2分支的提交附加到develop分支中的其他所有内容的顶部。

enter image description here

如果是这样,为什么会选择其中一个而不是另一个呢?
当我们确定在合并分支时git会快速前进更改时,使用合并命令:git checkout develop; git merge feature,将产生与变基命令:git rebase feature develop相同的项目历史。所以没有理由选择其中一个(如果两个分支可以快速前进)。只是你的个人偏好。

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