让我们说我在当地的回购中,它的分支是my_name/branch_A
当我git rebase <branch_B>
时,我有时会在我未修改的文件中出现很多冲突。
为什么会这样?
我想从branch_B
中获取所有文件的HEAD,除了我在my_name/branch_A
中修改过的文件。如果不手动解决我自己没有介绍过的这些冲突,怎么办呢?
答案 0 :(得分:7)
Rebase 副本提交(然后放弃原件)。这是问题的根源。
让我们看一个例子。首先,请注意我正在绘制提交图表,其中较旧的提交向左,较新的提交向右。提交在这里有单字母名称,而不是Git的真正的40个字符的哈希名称,如f1c93ab7...
。分支名称显示在右侧,箭头指向该分支的 tip commit ,因为这就是Git实际存储这些内容的方式。
您当前的分支名称为my_name/branch_A
,并且您还有一个名为branch_B
的分支。每个分支上有一些提交不在另一个分支上,而一些提交在两个分支上。与此同时,您的分支my_name/branch_A
从第三点开始分叉 - 因此您的分支上的提交不在branch_B
上,但不是“您的提交”:
...--A--B--C--D--E <-- branch_uhoh
\ \
\ I--J <-- my_name/branch_A
\
F--G--H <-- branch_B
您提交了I
和J
,现在您希望在提交H
之后提交这两个提交,即将您的提交重新修改为“在”提示之后branch_B
。
换句话说,没有进行提交C--D--E
。尽管如此,这些提交都在你的分支上。实际上,提交A
和B
也在您的分支上:这两个提交位于 all 分支上。
如果您现在运行git rebase branch_B
(当您还在分支机构时),Git必须弄清楚两件事:
名称branch_B
告诉Git 这两件事。要复制的提交是“my_name/branch_A
但不在branch_B
上的提交。那是C-D-E-I-J
。放置它们的地方是”在branch_B
的提示提交之后,即,在提交H
之后。
如果这一切都成功,Git会将您的分支名称设置为指向新副本:
...--A--B--C--D--E <-- branch_uhoh
\ \
\ I--J [abandoned]
\
F--G--H <-- branch_B
\
C'-D'-E'-I'-J' <-- my_name/branch_A
带有“prime”标记的名称(C'
等)是副本。
(您可以查看git rebase
将/将与git log <upstream>..HEAD
一起复制的提交,在这种情况下为git log branch_B..HEAD
。在大多数情况下,我会在此处添加--oneline
每次提交获得一行日志消息。)
好吧,如果这是问题,你该怎么办?显而易见的答案是:告诉Git不要复制C-D-E
。您想要这个结果:
...--A--B--C--D--E <-- branch_uhoh
\ \
\ I--J [abandoned]
\
F--G--H <-- branch_B
\
I'-J' <-- my_name/branch_A
也就是说,Git应该只复制branch_uhoh
和你的分支之间“之间”(之后,之后)的提交,以便提交I
和J
;但它应该将它们复制到(再次,之后,真的)branch_B
的提示。这样做的方法是写:
git rebase --onto branch_B branch_uhoh
换句话说,告诉rebase 两个事情,而不是告诉它一个事情并让它从中找出两个。
(但是你如何找到branch_uhoh
?嗯,“正确”的方式通常是记住它,但你可以运行git log --graph --decorate --oneline
并找到截止提交通过它的ID或显示的任何名称。而不是branch_uhoh
你可以剪切并粘贴实际截止提交的哈希ID。大多数情况下,你可以让 Git本身记住你的“上游”名称,你只在内部和上游进行重新定义,你需要没有参数:你只需运行git rebase
并完成所有工作。但是有特殊情况你需要移植提交,但这还不够;那么你需要git rebase --onto
。)