我的建议(或者,“如果我是橙色先生,我会怎么做”)是,从git fetch
. 现在我将在我的 repo 中有这个,这是 Blond 先生在他的 rebase 之后和他运行“git push -f”之前所拥有的。
M1 - M2 - M3
\ \
\ \
A1 - A2 A1' - A2'
一个重要的区别是,我的本地标签A
指向 rev A2,而远程标签remotes/origin/A
指向 A2'(Blond 先生反过来说,本地标签A
指向 A2' 并remotes/origin/A
指向 A2)。
如果我一直在处理名为“A”的分支副本,我将改为:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2'
(我的本地标签指向 A3 而不是 A2;或 A4 或 A5 等,具体取决于我应用了多少更改。)现在我要做的就是将我的 A3(和 A4,如果需要等)重新定位到 A2' . 一种明显的直接方式:
$ git branch -a
master
* A
remotes/origin/master
remotes/origin/A
$ git branch new_A remotes/origin/A
$ git rebase -i new_A
然后完全删除 revs A1 和 A2,因为修改后的在 new_A 中作为 A1' 和 A2'。或者:
$ git checkout -b new_A remotes/origin/A
$ git format-patch -k --stdout A3..A | git am -3 -k
(git am -3 -k
方法在git-format-patch
手册页中有描述)。
这些确实需要弄清楚我在 Blond 先生做他之前没有的东西rebase
,即识别 A1、A2、A3 等。
如果第二种方法成功,我最终会得到:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' - A3'
我的分支名称new_A
指向 A3'(我现有的A
分支仍然指向旧的 A3)。如果我使用第一种方法并且它成功了,我最终会得到同样的结果,只是我现有的分支名称A
现在将指向 A3'(并且我没有 A1-A2-A3 的旧分支的名称,即使它仍在我的仓库中;找到它需要通过 reflogs 或类似的)。
(如果我的 A3 需要修改为 A3',当然,交互式变基和“git am”方法都需要我的工作。)
当然也可以只是git merge
(如 Gary Fixler 的回答),但这将创建一个合并提交(“M”,没有数字,如下)并保持 A1 和 A2 的转速可见,给出:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' -- M
\_______________/
如果要保留原来的A1和A2,这是好事;如果你想摆脱它们,那是一件坏事。所以“做什么”取决于“你想要的结果是什么”。
编辑添加:我更喜欢 format-patch 方法,因为它保留了我的旧 A 分支名称,同时我确保一切都很好。假设一切正常并且很好,这是最后几个步骤:
$ git branch -m A old_A
$ git branch -m new_A A
然后,如果 old_A 可以完全放弃:
$ git branch -D old_A
或者,等效地,从分支删除开始,然后将 new_A 重命名为 A。
(编辑:另请参阅git rebase --onto
文档,以将 A3 等重新定位到 new_A 分支。)