如何在其基础分支基于 master 后对分支进行变基

How to rebase a branch after its base branch was rebased on master

我有一个分支 A,我在其中做了一些更改 a,然后我从 A 创建了一个新分支 B 以继续进行一些更改更改 b,因此 B 中的总更改为 a, b。最后,其他人将他们的更改 c 合并到 master 中,所以工作树现在看起来像这样:

- c (master)
 \ 
  - a (A) - b (B)

然后我将 A 重新设置为 master,将更改从 a 更改为 a' 并强制将它们推送到分支 A,因此工作树如下所示:

- c (master) - a' (A)
 \
  - a - b (B)

问题

如何将 B 变基为 A,以便仅更改新更改 b,然后工作树如下所示:

- c (master) - a' (A) - b' (B)

如果我在 B 上尝试 git rebase origin/A,那么它会尝试针对 c, a' 解析提交 a,这是我不想要的,因为我担心它会创建一个新的提交 a'',然后工作树将如下所示:

- c (master) - a' (A) - a'' - b' (B)

现在有没有办法只改变 b 变基? (我让 OFC 尝试 google 这个,但我没有找到任何具体的案例)

编辑:

我尝试在 B 上压缩 a'b,但这更糟,因为现在来自 b 的所有更改都被注册为冲突。为了说明,假设我:

  1. a 中添加了新行 l1
  2. b 中将该行更改为 l2
  3. 这一行在其他提交中未被修改 c
  4. 现在是冲突,因为 l1 是在 a' 中添加的,但是 l2 是在已撤销的提交 a'&b 中添加的。
git rebase --onto A a B

--onto A 使用 A 作为新基数。 a B 获取一组提交,如 git log a..B,在您的情况下仅包括 b。提交集被应用到新的基础上。

您可以随时使用interactive rebase来处理简单或复杂的情况。

git rebase -i A

在编辑页面,将a行中的前导pick修改为drop,或者直接删除整行。保存并退出。

如果 git rebase 不起作用,您也可以尝试 git cherry-pick 仅应用您想要的提交,然后将 B 重置为新头。

git checkout -b tmp A
git cherry-pick b
git checkout B
git branch B_bak
git reset tmp --hard
git branch -D tmp

如果出现问题,可以运行git checkout B && git reset B_bak --hard恢复B

How can I rebase B to A, so that only the new changes b are altered?

你可以简单地做:

git rebase A B

这等同于说“切换到分支 B 并将其变基到 A 之上”。 Git 不会 re-apply 提交 a 因为它可以确定 a' 已经引入了相同的更改。

补丁等效

当两个不同的提交(即具有不同 SHA-1 哈希的提交)引入相同的更改集时,它们被称为 等效补丁

您可以使用 --cherry-pick option of git log:

来确定两个分支之间哪些提交是补丁等效的

--cherry-pick
Omit any commit that introduces the same change as another commit on the “other side” when the set of commits are limited with symmetric difference.

在你的情况下,如果你这样做:

git log --oneline --cherry-pick --left-right A...B

您会看到提交 a'a 被排除在输出之外,因为它们是等效的补丁。1

当您在 A 之上变基 B 时,Git cherry-picks 来自 B 的提交并一次将它们应用到 A 之上。当它到达引入与现有提交相同更改的提交时,它将简单地跳过它并移动到下一个。


1 ... 符号(也称为 triple dot) selects 可从两个引用之一访问的提交,但不是两者。这对于 select 从其共同父级开始的两个不同分支中的“新”提交很有用。

事后找到了这篇文章:RECOVERING FROM UPSTREAM REBASE,但还没试过

编辑: 经过大量研究,正确答案是:

git checkout B
git rebase --onto A a

请参阅 I can't understand the behaviour of git rebase --onto 了解说明。

让rebase去寻找新基地的尖端所在的地方,然后从那里开始:

git rebase --fork-point A

并且如果您当前分支的上游已设置,则该选项和 --fork-point 选项都是默认设置,因此您的命令是

git rebase