是否可以变基到分支的中间(连接两端)?

Is it possible to rebase onto the middle of a branch (connecting both ends)?

不是重复的!

我看到的所有香草变基示例和花哨的图表都显示了如何将一个分支变基到另一个 branch/commit 的顶部。比方说,是否可以将分支 A 移动到分支 B 的具体中间位置?

        O--O--O Branch B             O--0--0--O--O Branch B
       /                            /  
O--O--O--0--0   Branch A     O--O--O

编辑:我不是在寻找变基到任意提交,而是在分支中间变基,连接两端

可以,你需要先

git checkout <commit>

然后rebase你的分支,然后推送到origin。

您要求从一个分支获取提交并将它们放在另一个分支的中间。 (这个措辞并不真的与git"thinks"关于分支和提交的关系,但我认为你的意思很清楚,所以好的...)

FROM:

x -- x -- A -- B -- C -- F -- G <--(branch_1)
      \
       D -- E <--(branch_2)

TO:

x -- x -- A -- B -- C -- D' -- E' -- F' -- G' <--(branch_1)

(不清楚你希望 branch_2 ref 在哪里结束 - 或者你是否只想删除它 - 但正确提交是一个更大的问题,你可以解决之后参考。)

重要的旁注:在此图中,D 之后的提交 替换为 D' 之后的提交;这是因为提交不能 "moved" 或以任何方式更改,所以我们所做的是创建新的提交。这意味着提交 DEFG(原始版本)已从您的历史记录中删除分支,如果分支被推送,这可能会导致问题。请参阅 git rebase 文档 (https://git-scm.com/docs/git-rebase) 以获取有关可能导致的问题以及如何解决这些问题的更多信息;请注意,如果不解决这些问题,其他开发人员可能会无意中撤消您的工作。

也就是说,有多种方法可以解决这个问题;通常你需要两个变基操作。

一种更直接的思考方式是,只需正常进行变基,然后进行交互式变基以更改提交顺序。

如果你想要更可编写脚本的东西,你可以从

开始
git rebase --onto branch_1~2 branch_1 branch_2

这里的 --onto 选项指定了一个不同于默认值的新碱基(默认值是 "the tip of the upstream")。因为我在此示例中将提交插入到 branch_1 的父项的父项之后,所以我可以使用 branch_1~2branch_1^^ 作为新的基本表达式。要重写的提交以通常的方式指定(在这种情况下“可以从 branch_2 访问但不能从 branch_1 访问)。所以你有

x -- x -- A -- B -- C -- F -- G <--(branch_1)
                     \
                      D' -- E' <--(branch_2)

现在您只需 rebase branch_1 以正常方式冷到 branch_2 的结尾。

git rebase branch_2 branch_1

屈服

x -- x -- A -- B -- C -- D' -- E' -- F' -- G' <--(branch_1)
                                ^(branch_2)

你的问题含糊不清,幸运的是,这幅图阐明了你想要什么。

如果我没有理解错的话,这是repo的输入状态

        M--N--P   <-- Branch B
       /
O--O--X--Y--Z     <-- Branch A

这就是您想要实现的目标。我用字母来表示提交。

        M--Y--Z--N--P   <-- Branch B
       /
O--O--X

首先你必须创建一个指向 M 的新分支 (C) 以使其在操作结束前保持可见

git branch C B~2

B~2替换为您从NB(包括两者)的实际提交数或使用绝对引用(现有分支或提交哈希)。

以下命令将 N-P 移动到 Z 之上。它将 B 中但不在 C 中的所有提交移动到 A

之上
# Move N-P on top of Z (A points to Z, B points to P, C points to M)
git rebase --onto A C B

最后一步是将 B 中但不在 C 中的所有提交移动到 C 之上:

# Move Y-Z-N-P on top of M (B still points to P, A still points to Z)
git rebase C B

回购现在看起来像这样:

        +-- Branch C
        v
        M--Y'-Z'-N'-P'  <-- Branch B
       /
O--O--X--Y--Z           <-- Branch A

分支A仍然指向原来的Z提交;原来的 Y 提交仍然存在。当前分支是 B.

提交 Y'Z'N'P'YZNP' 的副本P。它们仅在提交日期和父级上与原件不同;没有代码更改。

现在可以删除分支 AC。 (git branch -D A C).

详细了解 git rebase

我通常会先将分支 A 变基到分支 B。然后我会使用 git rebase -i HEAD~n(其中 n 是交互式编辑的提交数)并重新安排提交(通过简单地更改行的顺序编辑器)。