在主分支重新建立基础分支后,如何重新分支

时间:2020-09-04 07:31:59

标签: git branch rebase branching-and-merging

我有一个分支A,在其中进行了一些更改a,然后我从B创建了一个新分支A,以继续进行一些更改{ {1}},因此b中的总更改为B。最后,其他人将他们的更改a, b合并到master中,因此工作树现在如下所示:

c

然后,我将- c (master) \ - a (A) - b (B) 改成Master,将更改从A更改为a,并强行将其推到分支a',因此工作树如下所示:

A

问题

如何将- c (master) - a' (A) \ - a - b (B) 重新设置为B,以便仅更改新更改A,然后工作树如下所示:

b

如果我在- c (master) - a' (A) - b' (B) 上尝试git rebase origin/A时,它会尝试针对B来解决a的提交,我不希望这样做,因为我担心它将创建一个新的提交c, a',然后工作树将如下所示:

a''

有没有办法现在仅对变更- c (master) - a' (A) - a'' - b' (B) 进行基准调整? (我曾经有过OFC试图用Google搜索它,但是我没有找到任何具体可以解决这种情况的东西)

编辑:

我尝试在b上挤压a'b,但这甚至更糟,因为现在B的所有更改都被记录为冲突。为了说明这一点,假设我:

  1. b中添加了新行l1
  2. a中将该行更改为l2
  3. 在另一次提交b中未触碰此行。
  4. 现在这是一个冲突,因为在c中添加了l1,但在废止的提交a'中添加了l2

4 个答案:

答案 0 :(得分:1)

git rebase --onto A a B

--onto A使用A作为新基础。 a B获得一组类似git log a..B的提交,在您的情况下,该提交仅包含b。提交集将应用于新的基础。

您始终可以使用interactive rebase处理简单或复杂的案件。

git rebase -i A

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

如果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

答案 1 :(得分:0)

如何将B改成A,以便仅更改新更改b

您可以轻松地做到:

git rebase A B

这与说“ 切换到分支B并将其重新建立在A 之上”相同。 Git不会重新应用提交a,因为它可以确定a'已经引入了相同的更改。

补丁等效

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

您可以通过使用--cherry-pickgit log选项来确定两个分支之间哪些提交等同于补丁:

--cherry-pick
当提交集受到对称差异限制时,请忽略任何与“另一端”的另一次提交引入相同更改的提交。

如果您这样做,则:

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

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

当您将B置于A之上时,Git cherry-picks 来自B的提交并将其应用于A之上一次一个。提交与现有更改相同的更改时,只需跳过该更改并移至下一个。


1 ...表示法(也称为triple dot)从两个引用中的一个引用中选择一个提交,但是两个引用都不是。从共同的父级开始,选择两个不同分支中的“新”提交很有用。

答案 2 :(得分:0)

事实上,我发现了这篇文章:RECOVERING FROM UPSTREAM REBASE,但我还没有尝试过。

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

git checkout B
git rebase --onto A a

有关说明,请参见I can't understand the behaviour of git rebase --onto

答案 3 :(得分:0)

告诉基地重新寻找过去新基地的尖端并从那里开始:

git rebase --fork-point A

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

git rebase