git:冲突提交在哪里进行变基

时间:2014-02-11 12:13:58

标签: git rebase

假设我有这样的提交历史

              master
               |
|A| -> |B| -> |E|
        |
       |C| -> |D|
               |
              hotfix

假设提交E和D有冲突。现在,根据docs,在 rebase

之后
$> git checkout hotfix
$> git rebase master
# fix conflicts
$> git add -A
$> git rebase --continue
$> git push --force # rewrite history of branch hotfix on remote

我将以

结束
              master
               |
|A| -> |B| -> |E|
               |
              |C| -> |D|
                      |
                    hotfix

但是,我看不到我的合并/冲突结果在哪里? 如果我再次 rebase

$> git rebase master

我不希望再次发生同样的冲突,对吧?

最后一个问题,如果提交D在提交E之前,我上面显示的图表(在rebase之后的结果)是否仍然相同?

2 个答案:

答案 0 :(得分:5)

  

但是,我没有看到我的合并/冲突结果在哪里?

当你将git存储在.git目录下的临时区域中时,将临时对象存储起来。 (例如,.git/rebase-merge。)如果存在冲突,将要求您在执行rebase的过程中解决它们。

  

如果我再次做出反抗......我不希望再次发生同样的冲突,对吗?

不,你不会再次得到同样的冲突,因为你已经在之前的(第一次)rebase中解决了这些冲突。

  

最后一个问题,如果提交D在提交E之前,我上面显示的图表(在rebase之后的结果)是否仍然相同?

CD的结果,它仍然是相同的,因为它们将应用于E的顶部 - 主人的提示,但是在这两种情况下,它都不完全是您绘制的图表。主要区别在于提交将是D'C',即使它们与DC完全相同,它们也是新的提交,如果没有反叛冲突。

答案 1 :(得分:3)

当你做一个底板时,你所做的git“幕后操作”实际上是一系列的挑选。如果你以不同的方式标记提交,那就更明显了:让我们调用CDC'D'的“新”版本。而且,让我们把旧的留在那里,但“放弃”(失去和孤独,就像它)。所以我们从这开始(我已经颠倒了箭头,因为提交指向他们的父提交,而不是他们的孩子:EB作为父,DCCBBA):

A <-- B <-- E    <-- master
       ^
        \
          C <-- D   <-- hotfix

要执行rebase,git cherry-picks提交C,使C'E作为其父级;然后挑选D,打算用D'作为其父级C'。此时存在冲突(正如您所说),因此整个过程停止并使您解决冲突并继续。这最终生成D',然后git重写hotfix标签以指向D'

A <-- B <-- E    <-- master
      ^      ^
      |       \
      C - D    \
                \
                 C' <-- D'  <-- hotfix

旧的提交CD实际上仍在那里(但没有分支标签 - 尽管在{{1}中仍然有对它们的引用分支reflog,暂时,rebase留下一个拼写为hotfix的特殊标签,指向ORIG_HEAD)。只是当你想看到什么是“在分支D上”时,你现在看到了复制的提交。

您应用的冲突解决方案位于附加到提交hotfix的树中(因为那是发生冲突的地方并且您手动修复了它)。如果你挖掘D'的提交ID,或者使用reflog或D,你可以对ORIG_HEADD的树进行区分,看看你做了什么: / p>

D'
例如

。 (但这也包括$ git diff ORIG_HEAD hotfix 的变化,所以这可能也会产生误导。)

(松散地说,每个樱桃挑选都是通过将其被提取的提交树与其父树一起分离,然后将该差异作为补丁应用于提交“樱桃”被添加到其上来完成。所以挑选E并将其添加到C以获取E,git diffs C'B。然后,挑选C },git diffs DC,这次将差异应用到D。因此C'的树不会包含来自D的任何行,但E的树可能会。)