如何在不在 master 分支中获得主题提交的情况下重新定位到主题分支

How to rebase onto topic branch without getting topic commits in master branch

我有一个相当标准的用例,我将在我的主分支 (master) 之外创建一个主题分支,并且在未来,我想对我的主题分支进行更改,这些更改已被引入 master我创建了主题分支以确保我拥有最新的代码。我不喜欢在我的主题分支中合并提交,所以我更喜欢将来自 master 的提交变基到主题分支上,而不会将我的主题分支中的更改放入 master 中。有没有一种方法可以通过 rebase 将更改从 master 获取到主题分支,而无需将主题的提交也应用于 master?还是合并是我唯一的选择?

谢谢。

一个普通的 rebase 可以 做到这一点。如果您是主题分支的唯一开发人员,并且您只使用一个系统进行开发(以及一个用于备份的中央服务器),那么在您进行时简单地强制推送您重新设置基础的主题分支是非常容易的。

例如,昨天你有:

        F - G   <-- topic
      /
... E - H - I   <-- master

今天您决定在 master 上提交 I 对您的主题非常 I 重要并且您希望 topic 重新基于 master,所以(在分支 topic ) 你 运行:

git rebase master

这是做什么的:

        F - G   [abandoned]
      /
... E - H - I   <-- master
             \
              F' - G'   <-- topic

在您自己的存储库中。 (提交 F'G' 是原始 FG 的 "copies",这在下面的 "fork point" 中才真正开始重要。 ) 如果要将其复制到其他地方,则必须强制推送 topic,这会增加一些风险:

  • 如果其他人正在开发他们的 topic 副本怎么办?
  • 更糟糕的是,如果其他人也在做这个 rebase 并且有他们自己的额外提交 J 并且已经完成了强制推送以便集中备份服务器具有:

    ... E - H - I   <-- master
                 \
                  F' - G' - J   <-- topic
    

好吧,如果没有 "someone else",这两种情况都不可能发生,您就没事了。

但是如果其他人怎么办?

您需要一个替代方案。您当然可以使用合并或挑选。但是你仍然可以使用 rebase,provided 你和所有 "someone else"s 同意这可能发生。然后你需要(或者至少强烈想要)一些更新的 git 工具:

  • --fork-point
  • --force-with-lease

--fork-point 所做的是使 git rebase 变得更聪明,这样您就可以使用移动的主题分支,并使用您自己的引用日志来确定哪些提交被复制,这样您就可以只 rebase 您的自己的作品而不是别人的。它并不完美,但它是一个很大的帮助。

--force-with-lease 所做的也许是最重要的。假设你正在执行上面的 rebase,而其他人已经完成了 rebase 并添加了一个新的提交 J。当您转到 git push 重新设置 topic 时,您告诉您的 git 和中央服务器 git 您想让 topic 指向提交G' 在服务器上, 但前提是它当前指向在服务器 G 上提交 。在这种情况下,"someone else" 会先于您进行强制租赁推送,因此在服务器上,topic 现在指向提交 J。这会使您的 force-with-lease push 失败,然后您可以 运行 git fetch 弄清楚发生了什么并相应地协调您自己的工作。

(请记住,这些单个大写字母中的每一个都代表一些独特的 40 个字符的 SHA-1。如果您在复制的 F'G' 之上有一个新的提交,您仍然可以假设服务器使用您在提交 G 中拥有的 ID,并且一切正常:服务器确实有该 ID,因为没有其他人推送过,或者没有,因为其他人推送过。那些是仅有的两种服务器端可能性。不过,您必须非常小心,因为在您的 git fetch 之后,您的 origin/topic 现在也指向提交 J。)