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尝试在commitD
上重放“A
->B
补丁”。但是,Git无法干净地应用此修补程序;粗略地说,Git本身无法确定应该保留这两行代码的哪个版本:
Git不知道该怎么做,它要求您解决冲突,您可以将file.txt的内容替换为
l1-rep2
l2
(这是有争议的,因为正如丹尼尔·伯默(Daniel Böhmer)在《金融时报》中指出的那样,这创造了一种风险)。然后阶段化并提交更改:
git提交-am“冲突解决”
现在运行git-rebase--continue
,然后git尝试在commitE
上重播“B
->C
补丁”。。。成功了!那块补丁用得很干净;因为提交B
和E
中的file.txt
的内容是相同的,所以这里没有任何冲突的原因,最终会导致
l1-rep2
l2