Git 为什么在我的重基操作中只有一次提交而不是两次提交会发生冲突?

Git 为什么在我的重基操作中只有一次提交而不是两次提交会发生冲突?,git,rebase,merge-conflict-resolution,Git,Rebase,Merge Conflict Resolution,我有rep1存储库,在master分支上有两个提交。这些提交具有以下内容的file.txt: line1 line2 我将rep1克隆到rep2中,并将远程分支签出为跟踪: git checkout --track rep1/master 然后在此存储库中,我将file.txt的第一行修改为: line1-modified-rep2 line2 作出承诺。然后将其第二行修改为 line1-modified-rep2 line2-modified-rep2 作出承诺。因此,在rep2中,我

我有
rep1
存储库,在
master
分支上有两个提交。这些提交具有以下内容的
file.txt

line1
line2
我将
rep1
克隆到
rep2
中,并将远程分支签出为跟踪:

git checkout --track rep1/master
然后在此存储库中,我将
file.txt的第一行修改为:

line1-modified-rep2
line2
作出承诺。然后将其第二行修改为

line1-modified-rep2
line2-modified-rep2
作出承诺。因此,在
rep2
中,我向跟踪远程
rep1/master
分支的
master
分支添加了两个提交

现在我将产生一个冲突。在远程
rep1
存储库中,我创建了第三次提交(已经有两次提交),修改第一行和第二行的
file.txt

line1-modified-rep1
line2-modified-rep1
好了,现在我们都准备好合并冲突了。我将提交从
rep2
推送到
rep1
,被拒绝,并在提示
rebase
时选择此选项

现在,我读到,
rebase
将在
rep1
的同步第三次提交(使用前缀为
-rep1
的修改行)的基础上应用我从
rep2
提交的两次提交(其中我修改了两行前缀为
-rep2
),因此我预计会出现两次合并冲突:

  • 当应用来自
    rep2
    的第一次提交时,行
    line1-modified-rep1与line1-modified-rep2
    将发生冲突
  • 当应用来自
    rep2
    的第一次提交时,行
    line2-modified-rep1与line2-modified-rep2
    将发生冲突
  • 但是只有一个合并冲突,在解决冲突后,我可以成功地将提交推送到
    rep1
    。我错过了什么

    对冗长的阐述表示抱歉,我试图尽可能清楚地阐述我的观点

    编辑:

    因此,重设基础之前的设置如下所示:

    A--D (rep1)
     \
      B--C (rep2)
    
    添加了解析过程的屏幕截图:

    因此,冲突解决后的结果文件包含以下行:

    line1-modified-rep2
    line2
    
    这是phpstorm记录的git命令日志(源代码为
    rep1
    此处):


    查看您的屏幕截图,您没有在第二次提交时应用冲突。检查PhpStorm的更改->日志,您应该会在
    remote/master
    上看到两个提交。或者甚至三个,从git的输出来看

    Applying: rep2-commit 2
    Applying: rep2-commit 3
    
    编辑

    第二次未出现冲突的原因是您已将其合并,因此文件正处于
    rep2 commit 2
    状态。如果您选择进行rep1更改,则会产生更多冲突。

    我的两分钱。 在启动rebase之前,您遇到了如下情况:

    A--B--C--D--E报告2
    
    \
    
    F rep1

    在重新设定基准后,您将获得

    A--B--C
    
    \
    
    F--D'--E'代表2

    对吧?

    根据,我的理解是提交D和E的内容首先保存在临时区域中。提交D首先应用于提交F之上,生成冲突。冲突解决结束时,将创建“提交D”。然后将提交E应用于提交D'之上。Commit E是在Commit D之后对file.txt上第2行的修改。所以我的观点是:解决冲突以生成D'是关键步骤。根据所做的选择,commit D'的content file.txt等于commit D中file.txt的内容。在这种情况下,在commit D上生成E'时不会有任何冲突。

    TL;博士 在重新基础操作的开始处只发生一个冲突。由于您解决冲突的方式,第二个补丁可以干净地应用;没有理由再发生冲突

    更多细节 为了完整起见,下面是如何从命令行重新创建玩具示例的简化版本;为了方便起见,我将
    file.txt中的行缩短了一点:

    mkdir rep1
    cd报告1
    初始化
    printf“l1\nl2\n”>file.txt
    git add touch.txt
    git提交-m“初始提交”
    光盘
    git克隆rep1 rep2
    为清晰起见,git remote重命名origin rep1
    cd报告2
    sed-i'.txt''s/l1/l1rep2/'file.txt
    git commit-am“将'rep2'附加到第一行”
    sed-i'.txt''s/l2/l2rep2/'file.txt
    git commit-am“将'rep2'附加到第二行”
    cd../rep1
    sed-i'.txt''s/$/rep1/'file.txt
    git commit-am“将'rep1'附加到两行”
    cd../rep2
    git获取
    
    在所有这些命令之后,您的
    rep2
    repo如下所示(每个提交下面都显示了
    file.txt
    的内容):

    现在,在
    rep2
    中运行

    git rebase rep1/master
    
    要理解在这个重基过程中会发生什么,请记住,重基只不过是一系列的cherry pick操作,然后是一些分支洗牌;这在本文中得到了很好的解释

    首先,Git尝试在commit
    D
    上重放“
    A
    ->
    B
    补丁”。但是,Git无法干净地应用此修补程序;粗略地说,Git本身无法确定应该保留这两行代码的哪个版本:

    Git不知道该怎么做,它要求您解决冲突,您可以将
    file.txt的内容替换为

    l1-rep2
    l2
    
    (这是有争议的,因为正如丹尼尔·伯默(Daniel Böhmer)在《金融时报》中指出的那样,这创造了一种风险)。然后阶段化并提交更改:

    git提交-am“冲突解决”
    

    现在运行
    git-rebase--continue
    ,然后git尝试在commit
    E
    上重播“
    B
    ->
    C
    补丁”。。。成功了!那块补丁用得很干净;因为提交
    B
    E
    中的
    file.txt
    的内容是相同的,所以这里没有任何冲突的原因,最终会导致

    l1-rep2
    l2