【问题标题】:Rebasing and what does one mean by rebasing pushed commits变基以及变基推送的提交意味着什么
【发布时间】:2010-04-26 16:28:15
【问题描述】:

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

【问题讨论】:

    标签: git rebase


    【解决方案1】:

    要理解这一点,我们需要了解一下 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 上重新播放这些提交您要变基的分支(在本例中为 master)。 Git 实际上会在 master 之上创建新的提交来表示您的更改:在图中,这些提交称为 e' 和 f'。 Git 不会删除您之前的提交:e 和 f 保持不变,如果 rebase 出现问题,您可以直接回到以前的状态。

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

    【讨论】:

      【解决方案2】:

      ProGit book 有一个good explanation

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

      当你变基的东西,你 放弃现有的提交和 创建新的相似但 不同的。如果你推送提交 某处和其他人把它们拉下来 并以此为基础,然后你 用 git rebase 重写这些提交 再把它们推上去,你的 合作者将不得不重新合并 他们的工作和事情会变得一团糟 当你试图把他们的工作拉回来时 进入你的。

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

      【讨论】:

      • 感谢您的解释。所以,为了让我的理解更清楚,在我推送某些更改之后,我不应该使用git rebase(--interactive ?)来重写那个历史,这肯定是失败的秘诀。另一方面,如果我已经重新确定了某些更改主题分支(从分支 X)并推送它,在另一个开发人员更改主题分支后再次变基是完全正常的。从本质上讲,我使用merge 已经有一段时间了,但我们和darwinweb.net/articles/86 在同一条船上,历史几乎无法使用。
      • @Hemant:在推送到公共存储库后重新提交提交通常是一个坏主意。话虽如此,如果您的工作流程与他们的相似,您引用的 darwinweb 文章中的建议听起来很合理。请参阅我的更新回复以获取可能有帮助的其他参考资料列表。
      • 请将关于“Private Managed Team”的“ProGit”页面链接更新为git-scm.com/book/en/…
      • 所以从技术上讲,git 提交保持不变,但“放弃现有提交并创建相似但不同的新提交”只是具有不同 sha1 id 的相同提交?好吧,这将是我能想到的唯一明显的方式,为什么合作者必须重新合并他们自己的工作!
      • @Ciastopiekarz,这是因为您正在重写上游存储库中的历史记录,而其他开发人员的本地存储库可能有指向它的指针。现在他们的指针已经过时了:git 客户端别无选择,只能使用较旧的指针并依靠人类来整理其余部分。这是一个重新合并,它可能非常混乱,有很多必须手动整理的令人困惑的更改!因此,建议永远不要对已经推送到上游仓库的任何内容进行 rebase。这是一个很好的建议,除非您是知识渊博的专家,否则不应忽视它。
      【解决方案3】:

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

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

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

      【讨论】:

      • +1。我认为 git.git 的 pu 分支是一个非常有用的示例,说明了如何在(公共)工作流程中使用变基。对于那些不熟悉它的人,一般的想法是在next(合并到master之前的不稳定分支)中重新设置没有任何提交的主题分支,然后通过重置为next重建pu分支,并合并所有主题分支。 (来源:Documentation/howto/maintain-git.txt git.kernel.org/?p=git/git.git;a=blob;f=Documentation/howto/…
      • +1 表示“在 Git 中重写历史就像在现实世界中一样:你需要一个阴谋”
      • “如上文所述,由于 pu 是一次性分支,因此无需发布公告。” git-scm.com/docs/gitworkflows我们在工作中做类似的事情,“TEMP-something-latest”是一个丢弃分支,它是最新更改的组合,它可以是多个功能分支的合并,可以在任何时候删除和重新创建时间,不应该被开发。
      【解决方案4】:

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

      Rebase considered harmful 是一个很好的概述,我认为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-24
        • 2014-09-30
        • 2019-02-21
        • 2021-12-19
        • 1970-01-01
        • 2015-04-22
        • 2015-06-18
        相关资源
        最近更新 更多