112

人们常说,你不应该对你已经推送的提交进行rebase。那可能是什么意思?

4

4 回答 4

245

要理解这一点,我们需要了解一下 git 的工作原理。git 存储库是一个树结构,其中树的节点是提交。这是一个非常简单的存储库的示例: 当你分叉时

它在 master 分支上有四个提交,每个提交都有一个 ID(在本例中为 a、b、c 和 d)。您会注意到 d 当前是 master 分支的最新提交(或 HEAD)。 在此处输入图像描述

在这里,我们有两个分支:master 和 my-branch。您可以看到 master 和 my-branch 都包含提交 a 和 b,但随后它们开始分歧:master 包含 c 和 d,而 my-branch 包含 e 和 f。b 据说是 my-branch 与 master 相比的“合并基础”——或者更常见的是,只是“基础”。这是有道理的:您可以看到 my-branch 是基于以前版本的 master。

所以假设 my-branch 已经过时了,你想用最新版本的 master 更新它。换句话说,my-branch 需要包含 c 和 d。您可以进行合并,但这会导致分支包含奇怪的合并提交,从而使审查拉取请求变得更加困难。相反,你可以做一个变基。

在此处输入图像描述

当你变基时,git 找到你的分支的基础(在本例中为 b),找到该基础和 HEAD 之间的所有提交(在本例中为 e 和 f),并在分支的 HEAD 上重新播放这些提交你正在重新定位(在这种情况下,主人)。Git 实际上会在 master 之上创建新的提交来表示您的更改:在图中,这些提交称为 e' 和 f'。Git 不会删除你之前的提交:e 和 f 保持不变,如果 rebase 出现问题,你可以回到过去的样子。

当许多不同的人同时在一个项目上工作时,拉取请求可能很快就会过时。“陈旧”的拉取请求是不再与开发主线保持同步的请求,需要在将其合并到项目之前对其进行更新。拉取请求过时的最常见原因是由于冲突:如果两个拉取请求都修改了同一文件中的相似行,并且一个拉取请求被合并,则未合并的拉取请求现在将发生冲突。有时,拉取请求可能会过时而不会发生冲突:可能代码库中不同文件中的更改需要您的拉取请求中的相应更改以符合新架构,或者可能是当有人不小心将失败的单元测试合并到主分支。不管是什么原因,

于 2015-01-31T22:28:51.930 回答
81

ProGit很好的解释

您的问题的具体答案可以在标题为“变基的危险”的部分中找到。该部分的引述:

当你 rebase 东西时,你放弃了现有的提交并创建了相似但不同的新提交。如果你将提交推送到某个地方,而其他人将它们拉下来并基于它们进行工作,然后你用 git rebase 重写这些提交并再次推送它们,你的合作者将不得不重新合并他们的工作,当你尝试时事情会变得一团糟把他们的工作拉回你的工作。

更新:
根据您在下面的评论,听起来您的 Git 工作流程有困难。以下是一些可能有帮助的参考资料:

于 2010-04-26T16:37:05.540 回答
70

变基重写历史。如果没有人知道那段历史,那很好。然而,如果这段历史是众所周知的,那么在 Git 中重写历史就像它在现实世界中所做的那样:你需要一个阴谋。

阴谋真的很难保持在一起,所以你最好避免一开始就重新设置公共分支。

请注意,有一些成功阴谋的例子:puJunio C. Hamano 的 git 存储库(Git SCM 的官方存储库)的分支经常被 rebase。这样做的方式是,几乎所有使用Git 的人都pu订阅了 Git 开发者邮件列表,并且分支被重新定位的事实pu在邮件列表和 Git 网站上得到了广泛宣传。

于 2010-04-26T17:45:26.137 回答
6

变基会改变存储库的历史记录。如果您将提交推送到世界各地,即让其他人可以使用它们,然后您改变了对提交历史的看法,那么与拥有您旧历史的任何人一起工作变得困难。

我认为Rebase 被认为有害是一个很好的概述。

于 2010-04-26T16:40:50.800 回答