为什么我们永远不会对已被推送的提交使用rebase

时间:2018-02-09 14:40:35

标签: git

我仍在用VSTS和Git弄湿我的脚。我理解主分支中的更改需要进入功能分支的情况,但这些"提醒"或提示对我来说没有意义。 下面的陈述是什么意思? https://docs.microsoft.com/en-us/vsts/git/tutorial/rebase?tabs=visual-studio

【引用】

  

永远不要重新推送已经推送并与他人共享的提交。该   这个规则的唯一例外是当你确定没有人在你的   团队正在使用您推送的提交或分支。

在进一步阅读并且来自SVN之后,我想我明白为什么做出上述陈述:

  

永远不要强行推动其他人正在进行的分支。只有强行推动   你独自工作的分支机构。

这将是类似的"对于SVN的情况,其中:(1)你有一个其他人正在处理的本地分支,然后(2)直接在trunk中修复bug,然后(3)将这些更改合并到你的本地分支和(4)提交本地分支中的更新,从而迫使在该本地分支上工作的任何其他人获得更新并可能发生合并冲突

3 个答案:

答案 0 :(得分:6)

Ashish Mathew's answer链接到Pro Git书并引用它是正确的,但您可能需要更多背景才能真正理解它。但我想先说“永远”这个词太强大了。可以在一个条件下重新发布已提交的提交:每个必须处理所创建问题的人都已事先同意处理所创建的问题。

那么,这样做会产生什么问题呢?答案在于引用:rebase通过复制提交来工作。

Git为每个提交都有一个真正的“真实名称”,即提交的哈希ID。真正的名称 - 哈希ID - 是Git 找到基础数据的方式,以及当您将两个Gits相互连接时,它们传输数据的方式。 (实际上,这些哈希ID用于Git的所有四种内部对象类型,尽管你自己主要处理提交。)

任何给定提交的哈希ID都是唯一的,而显然完全随机 - 但实际上,它是完全确定的,是根据提交内部的数据计算的。 (这是该数据的密码哈希。)因此,您的Git可以连接到整个Universe中任何位置的任何其他Git,如果您的Git在另一个Git上传播原始哈希ID,如8279ed033f703d4115bee620dccd32a9ec94d9aa,则两个Gits可以立即告诉他们是否都有这样的提交。如果两个Gits都有提交,则无所事事;但如果只有一个 Git有提交,另一个Git会要求获得一份副本。

(传输总是一种方式:git fetch让你的Git调用另一个Git并从下载项目,而git push让你的Git调用另一个Git和将项目发送到它们。没有根本原因你不能同时做到这两个,但是这些命令都是用单向传输编写的。)

这种做一个非常简单的有/想要交换的能力是Git如何快速传输只有必要的对象:即使你有一个相当胖的存储库,例如Linux内核权重的存储库今天,超过700k的提交和大约2.4 GB的存储库数据库 - git fetch命令很快:

$ time git fetch

real    0m0.457s
user    0m0.228s
sys 0m0.087s
$ 

(今天早上我跑了git fetch,因为我从去年年底开始没有更新这个内核副本,所以速度要慢很多。那个花了大约3秒的CPU时间和大约10.5秒的时间实时,带来超过11853个物体。)

无论如何,所有这些的简短版本是Git倾向于像源代码控制系统的Borg:无论有什么,当我将Git连接到你的时候,我添加你拥有的所有东西 我的存储库。我保留我之前拥有的一切!

所以,如果你对我现在发布的提交提交使用git rebase,因为我之前从你那里得到了它们 - 你会像在引文中那样将你现有的一些提交复制到你提交的新提交中认为是新的和改进的。然后,您将切换到新的提交,放弃您复制的令人讨厌的旧提交。当我将我的 Git连接到你的 Git时,我最终将使用 旧的和

这似乎并不那么糟糕 - 但问题是我的Git将我的存储库中的所有提交视为宝贵的,所以现在我既有旧的也有新的。我没有放弃旧的。如果我已经构建了使用旧提交的新提交,我现在必须以某种方式将我构建的工作与您复制的工作分开。

有一些工具可以帮助解决这个问题 - 特别是git rebase --fork-point - 但它们并不是最精彩的事情。在我拿起您的重新提交后,它们需要相当快速地使用才能生效。因此,我需要知道,最好提前知道,您将重新定位已发布的作品 - 我已经拥有的作品 - 以便我准备做任何必须做的事情来修改我的处理你的重新定位的工作。

如果我们事先已经同意了这一点,并且我们都知道如何做到这一点,那么 可以来修改已发布的提交。如果不是,那么,你可能会为其他人做很多工作,也许是许多“其他人”,他们可能不知道如何使用(不那么好)工具来处理“上游变种”。

答案 1 :(得分:0)

Rebase操作具有潜在的破坏性"一个,因为它是如此强大。 rebase的强大之处在于它可以重写特定分支的提交历史。在你考虑在两个或更多人不同意历史记录的任何情况下会发生什么事情之前,这似乎不是什么大事。

当您将分支机构推送到服务器时,您不仅要推动分支机构的当前状态,还要推送其历史记录。在应用/比较更改时,任何将来的合并或分支都会考虑此历史记录。

如果您将已经被推送到服务器的分支机构重新绑定,那么任何已经撤出分支的人现在都无法在他们的提交中绘制一条干净的路径。因此,他们将面临不一致的历史,并且整合存储库中的合并冲突

处理这件事的不幸的灵魂可能不会对你产生温暖和模糊的感觉,因为你只是花费了他们非常大的时间和精力。

答案 2 :(得分:0)

来自Pro Git书。

  

当您重新设置内容时,您将放弃现有提交并创建相似但不同的新提交。如果你将提交推送到某个地方而其他人将它们拉下来并依赖它们,然后你用git rebase重写这些提交并再次推送它们,那么你的协作者将不得不重新合并他们的工作,当你试图将事情变得混乱把他们的工作拉回你的工作。