如何解决上游分支的强制推送问题?

eft*_*ft0 3 git git-push git-rebase git-rewrite-history

我有一个branchX用作some-remote/base-branch其上游分支的功能分支。我刚刚发现some-remote/base-branch它的历史被强制推动改写了。涉及哪些问题以及如何解决?

eft*_*ft0 8

这带来的最大问题是,您应该删除从旧上游分支重写的修订,以便当您推送功能分支时,它们不再存在。

如果您尝试在新分支之上重新建立分支(例如,git checkout branchX; git fetch some-remote; git rebase some-remote/base-branch),git 不仅会重新建立功能分支的修订版本还会重新建立已经从新重写的分支中移出的修订版本...这是不行。如果合并也是一样。因此,简单的git pull(合并或变基)不会让你摆脱困境......实际上,你很可能会让自己陷入更深的困境。

如果您决定保留它们,就好像什么也没发生一样,您将进入上游分支的历史记录、已从中删除的修订,并且很可能不需要保留它们(因为......为什么分支的历史首先被重写了,对吧?如果重写了,那些旧的修改就不会再看到了)。

这看起来似乎是一件大事,但坦率地说,摆脱困境并不难。诀窍是将功能分支的修订移动到新重写的分支之上,留下旧分支。因此,这就是过程,假设您的功能的分支是一条没有合并的直线:

誓言

在功能分支的历史记录中(例如,使用git loggitk或任何其他必要的方式)查找功能分支中旧上游分支的最后修订版本。假设您获得了该修订版的 ID,我们将其称为old-base-rev

从远程获取以获取上游分支新重写的历史记录。

git fetch some-remote # adjust to the name of your remote, of course
Run Code Online (Sandbox Code Playgroud)

转折点

这就是魔法发生的地方:

git rebase --onto some-remote/base-branch old-base-rev branchX
Run Code Online (Sandbox Code Playgroud)

这样,git 只会对实际构成功能分支本身而不是旧的上游分支的工作的修订进行变基。

威望

就是这样。您可以继续在您的分支上工作,就像什么都没发生一样。

其他可能性

如果您正在处理不直接的功能分支(它合并了上游分支而不是对其进行变基),您可以使用我提供的相同配方,但是,如果您在合并上游分支时必须解决冲突,那会很棘手。如果您想避免再次处理冲突,也许您可​​以尝试的最好方法是将功能分支的更改放入单个修订版中,然后尝试魔术。在找到基础分支的最后一个 ID 在功能分支中后:

git reset --soft old-base-rev
git commit -m "Single revision for feature X"
Run Code Online (Sandbox Code Playgroud)

现在,您的所有更改都已合并为old-base-rev. 然后您可以按照配方执行获取/变基步骤。

git fetch some-remote
git rebase --onto some-remote/base-branch old-base-rev branchX
Run Code Online (Sandbox Code Playgroud)