快进
git merge
和 git rebase
有什么区别?难道两者都没有实现保持历史线性并且没有合并提交吗?如果是这样,为什么人们会使用其中一种而不是另一种?如果不是,我认为这是真的,那么我没有看到的整个故事是什么?
谢谢!
当你领先于 main 时,两者都会做同样的事情。
如果你在 main 之前和之后,那么快进合并是不可能的,因为 master 上有更新的提交。但在这种情况下,您可以变基,根据 main 之前的提交创建新的提交。
当你领先于 main 时:
*E-*F-*G-*H-*I BRANCH
/
*A-*B-*C-*D MAIN
当您进行快进合并时,主指针会向前移动到分支的尖端。当您变基时,分支的每个提交都会移动到 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
那么你就不能快进将 E..I 合并到 main 中,因为 J..K 挡住了路。所以在这种情况下快进是不可能的。
但是你可以将 E..I 重新设置为 K:
*A-*B-*C-*D-*J-*K-*E'-*F'-*G'-*H'-*I' MAIN | BRANCH
但是发生的情况是,一个新的提交包含 E 的更改并附加到 main,然后一个新的提交包含 F 的更改并附加到 main...等等,直到来自分支的所有提交都被“在另一个分支上移动”/“重播”。结果又是一条没有分支和合并的历史记录。
因为必须重新应用提交并且可能解决冲突,所以实际提交将发生变化,生成新的提交 ID 等。
是的,快进是一种无需合并提交即可维护线性历史记录的方法。
快进
和git merge
有什么区别git rebase
当 git 执行快进时,无论你使用
git merge
还是git rebase
,都是一样的。git merge
合并 2 个分支将并不总是 快进。在这种情况下,您可以使用 git rebase
在合并分支中准备提交历史记录,以便实现快进合并。
git merge
让我们假设一个场景:您正在开发自己的项目。在某个时候,您想要添加一个您想到的功能。这有点具有挑战性,您需要在单独的分支中进行,看看是否可以构建它。
您的项目有一个名为
develop
的主分支。为了构建此功能,您创建一个名为 feature
的分支并切换到它。您致力于此功能并进行了多次提交。经过一段时间的黑客攻击,您已经成功构建了它。
此时,你的项目历史是这样的:
实际上,自从您转向在
develop
分支中进行构建和提交以来,feature
分支还没有新的提交。因此,不存在发散工作,即 feature
分支直接位于 develop
之前。当我们使用 feature
将 develop
合并到 git merge feature develop
时,我们将获得快进合并。这意味着,Git 不会生成合并提交,而只是将 develop
分支指向 feature
分支的尖端:
git rebase
让Git进行快进合并在第二种情况下:您需要为您的项目构建更多功能。您引入了更多的开发人员,并为他们提供了在各自的功能/主题分支中构建的功能。您自己正在
feature-2
分支中构建另一个功能。
在某个时刻,您已经完成了您的功能。但此时,您分配给他们构建功能的其他开发人员已经这样做了,并且已经将他们的工作合并到了
develop
分支:
现在,如果你像这样合并:
git merge feature-2 develop
,你将不会有快进合并,因为自从你上次分支以来,develop
已经随着新的提交而发展。为了实现快进合并,您必须将 feature-2
分支的基础更改为 develop
分支上的最新提交,例如 git rebase develop feature-2
。历史将如下所示:
关于
git rebase
的一点是,它将更改分支的基础,并按照新 ID 发生的顺序重新应用其提交。因此,提交在图像中显示为 c3'...c5'
。
一旦我们重新确定了
feature-2
分支的基础,我们现在就可以将其合并到develop
中:git merge feature-2 develop
,结果应该是快进。 feature-2
分支的提交将附加到 develop
分支中其他所有内容的顶部:
如果是这样,为什么要使用其中一种而不是另一种?
当我们确定 git 将从合并分支快速转发更改时,合并命令:
git merge feature develop
,将产生与 rebase 命令相同的项目历史记录:git rebase feature develop
。因此没有理由使用其中一种而不是另一种。只是您的喜好。