如何在其基础分支基于 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
的所有更改都被注册为冲突。为了说明,假设我:
- 在
a
中添加了新行 l1
。
- 在
b
中将该行更改为 l2
。
- 这一行在其他提交中未被修改
c
。
- 现在是冲突,因为
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
我有一个分支 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
的所有更改都被注册为冲突。为了说明,假设我:
- 在
a
中添加了新行l1
。 - 在
b
中将该行更改为l2
。 - 这一行在其他提交中未被修改
c
。 - 现在是冲突,因为
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
toA
, so that only the new changesb
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