为什么git rebase在我没有修改的文件中显示冲突?

sh0*_*731 3 git git-rebase

让我们说我在当地的回购,它的分支是 my_name/branch_A

当我这样做时git rebase <branch_B>,我有时会在我没有修改的文件中遇到很多冲突.

为什么会这样?我喜欢只获取所有文件的HEAD,branch_B除了我修改过的文件my_name/branch_A.如果不手动解决我自己没有介绍过的这些冲突,怎么办呢?

tor*_*rek 8

Rebase 复制提交(然后放弃原件).这是问题的根源.

我们来看一个例子.首先,请注意我正在绘制提交图表,其中较旧的提交向左,较新的提交向右.提交在这里有单字母名称,而不是Git真正的40个字符的哈希名称f1c93ab7....分支名称出现在右侧,箭头指向该分支的提示提交,因为这就是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
Run Code Online (Sandbox Code Playgroud)

你做了提交I,J现在你希望在提交之后提交这两个提交H,即,将你的提交重新修改为"在"之后branch_B.

换句话说,你没有提交C--D--E.尽管如此,这些提交都在你的分支上.实际上,提交A并且B也在您的分支上:这两个提交都在所有分支上.

如果你现在运行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
Run Code Online (Sandbox Code Playgroud)

带有"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
Run Code Online (Sandbox Code Playgroud)

也就是说,Git应该只复制那些"之间"(之后,真的)提示branch_uhoh和你的分支的提交,以便得到提交IJ; 但它应该将它们复制(再次,之后,真的)尖端branch_B.这样做的方法是写:

git rebase --onto branch_B branch_uhoh
Run Code Online (Sandbox Code Playgroud)

换句话说,告诉rebase 这两件事,而不是告诉它件事,让它从中找出两者.

(但你如何找到branch_uhoh?嗯,"正确"的方式通常是记住它,但你可以运行git log --graph --decorate --oneline并通过其ID或显示的任何名称找到截止提交.而不是branch_uhoh你可以剪切和粘贴.实际截止的哈希ID提交大多数情况下,你可以拥有的Git本身对你还记得"上游"的名字,而你只内到上游底垫,你需要参数:你只要运行git rebase和它所有的工作.但是有些特殊情况你需要移植提交,这是不够的;那么你需要git rebase --onto.)