Git Merge Fast-Forward 与 Git Rebase

New*_*ewo 23 git git-merge git-rebase fast-forward

git merge快进和快进有什么区别git rebase?难道两者都没有实现保持历史线性并且没有合并提交吗?如果是这样,为什么人们会使用其中一种而不是另一种?如果不是,我认为这是真的,那么我没有看到的整个故事是什么?

谢谢!

jes*_*ing 49

当你领先于 main 时,两者都会做同样的事情。

如果您在 main 之前和之后,那么快进合并是不可能的,因为 master 上有更新的提交。但在这种情况下,您可以变基,根据 main 之前的提交创建新的提交。

当你领先于 main 时:

            *E-*F-*G-*H-*I    BRANCH
           /
*A-*B-*C-*D                   MAIN
Run Code Online (Sandbox Code Playgroud)

当您进行快进合并时,主指针向前移动到分支的尖端。当您变基时,分支的每个提交都会移动到 MAIN 头部之后。最终结果是一样的:

*A-*B-*C-*D-*E-*F-*G-*H-*I MAIN | BRANCH
Run Code Online (Sandbox Code Playgroud)

当您领先于 MAIN 以及落后于 MAIN 时:

            *E-*F-*G-*H-*I    BRANCH
           /
*A-*B-*C-*D-*J-*K             MAIN
Run Code Online (Sandbox Code Playgroud)

那么你就不能快进地将 E..I 合并到 main 中,因为 J..K 挡住了路。所以在这种情况下快进是不可能的。

但你可以将 E..I 重新设置为 K:

*A-*B-*C-*D-*J-*K-*E'-*F'-*G'-*H'-*I'             MAIN | BRANCH
Run Code Online (Sandbox Code Playgroud)

但发生的情况是,进行了包含 E 更改的新提交并将其附加到 main,然后进行了包含 F 更改的新提交并将其附加到 main...等等,直到分支中的所有提交都已“移动” “/”在另一个分支上重播。结果又是一条没有分支和合并的历史记录。

因为必须重新应用提交并且可能解决冲突,所以实际提交将发生变化,生成新的提交 ID 等。


han*_*ter 5

是的,快进是一种无需合并提交即可维护线性历史记录的方法。

git merge快进和快进有什么区别git rebase

当 git 执行快进时,无论您使用git merge或 ,都是一样的git rebase
然而,使用 合并 2 个分支git merge并不总是快进。在这种情况下,您可以git rebase在合并分支中准备提交历史记录,以便实现快进合并。

当可以快进时git merge

让我们假设一个场景:您正在开发自己的项目。在某个时候,您想要添加一个您想到的功能。这有点具有挑战性,您需要在单独的分支中进行,看看是否可以构建它。

您的项目有一个名为 的主分支develop。要构建此功能,您需要创建一个名为 的分支feature并切换到它。您致力于此功能并进行了多次提交。经过一段时间的黑客攻击,您已经成功构建了它。

此时,你的项目历史是这样的:

特征分支的演变历史

实际上,develop自从您转向在分支中构建和提交以来,分支就没有新的提交feature。因此,不存在发散工作,即feature分支直接位于 之前develop。当我们合并featuredevelopusing 时:

git checkout develop
git merge feature
Run Code Online (Sandbox Code Playgroud)

我们将得到一个快进合并。这意味着,Git 不会生成合并提交,而只是将develop分支指向分支的尖端feature

快进合并

用于git rebase使Git执行快进合并

在第二种情况下:您需要为项目构建更多功能。您引入了更多的开发人员,并为他们提供了在各自的功能/主题分支中构建的功能。您自己正在分支中构建另一个功能feature-2

在某个时刻,您已经完成了您的功能。但此时,您分配给他们构建功能的其他开发人员已经这样做了,并且已经将他们的工作合并到分支中develop

变基前的功能分支

现在如果你像这样合并:

git checkout develop
git merge feature-2
Run Code Online (Sandbox Code Playgroud)

您不会进行快进合并,因为develop自上次分支以来已经随着更新的提交而发展。为了使快进合并成为可能,您必须将分支的基础更改为分支feature-2上的最新提交,例如:develop

git rebase develop feature-2 #checkout feature-2 then rebase
Run Code Online (Sandbox Code Playgroud)

这就是现在的历史:

rebase后的功能分支

git rebase会更改分支的基础,并按照新 ID 发生的顺序重新应用其提交。因此,提交c3'...c5'如图所示。

一旦我们重新建立了feature-2分支,我们现在可以将其合并到develop

git checkout develop
git merge feature-2
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

如果是这样,为什么人们会使用其中一种而不是另一种?

当我们确定 git 在合并分支时会快速转发更改时,合并命令:git checkout develop; git merge feature,将产生与 rebase 命令相同的项目历史记录:git rebase feature develop。因此没有理由使用一个而不是另一个(如果两个分支可以快进)。只是你的喜好。