如何在不破坏树的情况下重新设置推送的分支?

How to rebase pushed branches without ruining tree?

我是唯一一个在存储库中工作的开发人员,所以破坏人们的流程没有问题。但是,当我在本地重新设置基准然后尝试将其推送到 Bitbucket 时,它返回告诉我需要提取最新的更改。我这样做了,rebase 完全毁了我干净的树。

有没有一种方法可以将变基推送到服务器,而无需额外 "Merge branch" 提交作为其中的一部分?

谢谢!

Rebase 基本上是一个 "copy some commits, then discard the old commits in favor of the new and supposedly improved commits" 操作。

例如,考虑这种情况:

...--A--B--E--F   <-- master
         \
          C--D--G   <-- feature (HEAD)

您已经完成了您的功能 feature,但无论出于何种原因,您必须在工作时在 master 上创建两个提交。所以现在feature可以重写了。

没有提交可以 永远 改变,所以实际上不可能 replace C 用新的和改进的变体,但我们可以创建一个新的和改进的 C' 来替换 C,使用临时分支或 Git 的 "detached HEAD" 模式:

                C'  <-- HEAD
               /
...--A--B--E--F   <-- master
         \
          C--D--G   <-- feature

提交 C' 对提交 F 的作用与提交 C 对提交 B 的作用相同。旧的(现在很糟糕)C 的父级是 B,而改进后的新的 C' 的父级是 F。所以现在我们需要将 D 复制到新的和改进的 D',然后对 G:

再次执行相同的操作
                C'--D'--G'  <-- HEAD
               /
...--A--B--E--F   <-- master
         \
          C--D--G   <-- feature

我们现在准备好了 git rebase 的最后一招。它从提交 G 中剥离名称 feature 并使 feature 指向 G' 而不是:

                C'--D'--G'  <-- feature (HEAD)
               /
...--A--B--E--F   <-- master
         \
          C--D--G   [abandoned]

由于我们甚至无法看到 被遗弃的提交,因此在您笔记本电脑的本地存储库中,历史似乎一直都是这样:您编写了提交 C' 基于 F,依此类推。哈希 ID 看起来是随机的;除了你,没有人会知道这一切。

仅...您对 Bitbucket 进行了 git push 次提交 C-D-G,或至少其中一些。 他们 有你的旧的和糟糕的提交,由 他们的 分支名称 feature 指出。你把你闪亮的新名字发给他们——git push origin feature——最后,你的Git礼貌地请他们把他们的feature名字移到指向提交 G' 而不是 G.

这当然会导致 他们 放弃提交 G 以支持新的和改进的 G'。这就是您希望他们做的。但他们会说:不,如果我那样做,我将失去我宝贵的承诺 G!

你所要做的就是告诉他们——或者让你的 Git 告诉他们——是的,我知道你可能会丢失一些提交,但无论如何都要这样做!也就是说,您 Git 向他们发送了一个强有力的命令,而不是礼貌的请求。

您这样做的方法是将 --force--force-with-lease 添加到您的 git push 命令中。这变成了礼貌的请求,请,如果可以,请将您的 feature 设置为命令:设置您的功能!

--force--force-with-lease的区别在于后者先增加了安全检查。而不是仅仅说 Set your name feature to point to commit G'!,你的 Git 会说:I think,根据我的信息,您的 feature 指向提交 G。如果是这样,请将其设置为指向 G'。如果没有,让我知道我搞砸了。

安全检查显然通常很好,但也没有必要如果你是唯一一个在 Bitbucket 上将新提交放入存储库的人。