为什么在我的rebase操作中只发生一次提交而不发生两次冲突? [英] Why does a conflict occur for only one commit instead of two in my rebase operation?
问题描述
我有 rep1
存储库,在 master
分支上有两次提交.这些提交的 file.txt
具有以下内容:
line12号线
我将 rep1
克隆到 rep2
中,并检出作为跟踪的远程分支:
git checkout --track rep1/master
然后在此存储库中,将 file.txt
的第一行修改为:
line1-modified-rep22号线
进行提交.然后将其第二行修改为
line1-modified-rep2line2-modified-rep2
进行提交.因此,在 rep2
中,我向 master
分支添加了两个提交,用于跟踪远程 rep1/master
分支.
现在我要产生冲突.在远程 rep1
存储库上,我创建第三次提交(那里已经有两次提交),将第一行和第二行中的 file.txt
修改为:
line1-modified-rep1line2-modified-rep1
好,现在我们都准备好合并冲突了.我将提交从 rep2
提交到 rep1
,被拒绝,并在提示输入 rebase
时选择此选项.
现在,我正在阅读 rebase
将应用来自 rep2
的两次提交(我在其中修改了两行,前缀为 -rep2
)从 rep1
向下同步的第三次提交的顶部(带有前缀为 -rep1
的修改行),因此我期望两个合并冲突:
- 当从
rep2
进行第一次提交时,line1-modified-rep1 vs line1-modified-rep2
行将发生冲突 - 将应用来自
rep2
的第一次提交,并且line2-modified-rep1 vs line2-modified-rep2
行将发生冲突
但是只有一个合并冲突,并且在解决该冲突时,我可以将提交成功推送到 rep1
.我在这里想念什么?
PS.很抱歉,冗长的阐述,我试图将案情安排得尽可能清楚.
因此,重新设置基准之前的设置如下:
A--D(rep1)\B--C(rep2)
添加了解决过程的屏幕截图:
因此,解决冲突后得到的文件包含以下几行:
line1-modified-rep22号线
这是phpstorm记录的git命令的日志(此处为 rep1
):
23:19:49.586:git -c core.quotepath = false获取原始文件--progress --prune远程:计数对象:5,已完成.[K远程:总计3(增量0),已重用0(增量0)[K从E:/rep1acc72ac..e6317e8主->起源/主人23:20:39.118:CD E:\ rep223:20:39.118:git -c core.quotepath = false重新设置原点/主节点首先,快退一下,在上面重播您的作品...正在申请:rep2-commit 2使用索引信息来重建基础树...M file.txt退回到修补基础和三路合并...自动合并file.txt冲突(内容):在file.txt中合并冲突无法合并更改.修补程序在0001 rep2-commit 2失败失败的修补程序的副本位于:e:/rep2/.git/rebase-apply/patch解决此问题后,运行"git rebase --continue".如果您希望跳过此补丁,请运行"git rebase --skip".要检出原始分支并停止重新基准化,请运行"git rebase --abort".23:24:33.418:CD E:\ rep223:24:33.418:git -c core.quotepath = false添加--ignore-errors-file.txt23:24:33.630:CD E:\ rep223:24:33.630:git -c core.quotepath = false rebase --continue正在申请:rep2-commit 2正在申请:rep2-commit 3
TL; DR
在变基操作的开始仅发生一个冲突.由于解决冲突的方式,第二个补丁很干净;没有其他冲突的原因.
更多详细信息
为完整起见,这是如何从命令行重新创建玩具示例的简化版本;为了方便起见,我稍微缩短了 file.txt
中的行:
<代码> mkdir rep1光盘rep1git initprintf"l1 \ nl2 \ n">file.txtgit添加touch.txtgit commit -m初始提交"光盘..git clone rep1 rep2git remote reset origin origin rep1#为清楚起见光盘rep2sed -i'.txt''s/l1/l1rep2/'file.txtgit commit -am将'rep2'附加到第一行"sed -i'.txt''s/l2/l2rep2/'file.txtgit commit -am将'rep2'追加到第二行"光盘../rep1sed -i'.txt''s/$/rep1/'file.txtgit commit -am将'rep1'追加到两行"光盘../rep2git获取
所有这些命令之后,您的 rep2
存储库如下所示(每次提交下方均显示 file.txt
的内容):
现在,在 rep2
中运行
git rebase rep1/master
要了解此重新设置过程中会发生什么,请记住,重新设置只不过是一系列的Cherry-pick操作,然后进行一些分支改组;在,如丹尼尔·博默(DanielBöhmer)在 您现在运行 I have I clone Then in this repository I modify first line of Make commit. Then modify its second line to be Make commit. So, here in the Now I'm going to generate a conflict. On the remote Ok, now we're all set for merge conflict. I push commits from Now, I was reading that But there is only one merge conflict and upon its resolution I can successfully push my commits to the PS. Sorry for the lengthy elaboration, I tried to lay out my case as clear as possible. EDIT: So the setup before rebase is the following: Added screenshots of the resolution process:
So the resulting file after the conflict resolution contains these lines: This is a log of git commands recorded by phpstorm (origin is
Only one conflict occurs at the beginning of the rebase operation. Because of the way you resolve that conflict, the second patch applies cleanly; there is no cause for additional conflicts. For completeness, here is how to recreate a simplified version of your toy example from the command line; I've shortened the lines in After all those commands, your Now, in To understand what happens during this rebase, remember that a rebase is little more than a series of cherry-pick operations, followed by some branch shuffling; this is well explained in the Think like a Git tutorial. First, Git attempts to replay the " Not knowing what to do, Git asks you to resolve the conflict, which you do by replacing the contents of (which is controversial, because that creates an evil merge, as pointed out by Daniel Böhmer in his comment). You then stage and commit the changes: You now run 这篇关于为什么在我的rebase操作中只发生一次提交而不发生两次冲突?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! git commit -am冲突解决"
git rebase --continue
,然后Git尝试在其顶部重播" B
-> C
补丁"提交 E
...和成功!该补丁完全适用;因为提交 B
和 E
中的 file.txt
的内容是相同的,所以这里没有任何冲突的原因,并且最终导致rep1
repository with two commits on master
branch. These commits have file.txt
with the following content:line1
line2
rep1
into rep2
and checkout remote branch as tracking:git checkout --track rep1/master
file.txt
to be:line1-modified-rep2
line2
line1-modified-rep2
line2-modified-rep2
rep2
I have added two commits to master
branch that tracks remote rep1/master
branch.rep1
repository I create third commit (there are already two there) modifying file.txt
on the first and second lines to be:line1-modified-rep1
line2-modified-rep1
rep2
to rep1
, get rejected and when prompt for rebase
select this option. rebase
would apply my two commits from rep2
(where I modified two lines with prefix -rep2
) on top of the synced down third commit from rep1
(with modified lines with prefix -rep1
) and so I'm expecting two merge conflicts:
rep2
would be applied and the lines line1-modified-rep1 vs line1-modified-rep2
will get conflictedrep2
would be applied and the lines line2-modified-rep1 vs line2-modified-rep2
will get conflictedrep1
. What am I missing here?A--D (rep1)
\
B--C (rep2)
line1-modified-rep2
line2
rep1
here):23:19:49.586: git -c core.quotepath=false fetch origin --progress --prune
remote: Counting objects: 5, done.[K
remote: Total 3 (delta 0), reused 0 (delta 0)[K
From E:/rep1
acc72ac..e6317e8 master -> origin/master
23:20:39.118: cd E:\rep2
23:20:39.118: git -c core.quotepath=false rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: rep2-commit 2
Using index info to reconstruct a base tree...
M file.txt
Falling back to patching base and 3-way merge...
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Failed to merge in the changes.
Patch failed at 0001 rep2-commit 2
The copy of the patch that failed is found in:
e:/rep2/.git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
23:24:33.418: cd E:\rep2
23:24:33.418: git -c core.quotepath=false add --ignore-errors -- file.txt
23:24:33.630: cd E:\rep2
23:24:33.630: git -c core.quotepath=false rebase --continue
Applying: rep2-commit 2
Applying: rep2-commit 3
TL;DR
More details
file.txt
a bit, for convenience:mkdir rep1
cd rep1
git init
printf "l1\nl2\n" > file.txt
git add touch.txt
git commit -m "initial commit"
cd ..
git clone rep1 rep2
git remote rename origin rep1 # for clarity
cd rep2
sed -i '.txt' 's/l1/l1rep2/' file.txt
git commit -am "append 'rep2' to first line"
sed -i '.txt' 's/l2/l2rep2/' file.txt
git commit -am "append 'rep2' to second line"
cd ../rep1
sed -i '.txt' 's/$/rep1/' file.txt
git commit -am "append 'rep1' to both lines"
cd ../rep2
git fetch
rep2
repo looks as follows (the contents of file.txt
is shown underneath each commit): rep2
, you rungit rebase rep1/master
A
->B
patch" on top of commit D
. However, Git cannot apply this patch cleanly; roughly speaking, Git, on its own, has no way of figuring out which versions of the two lines it's supposed to keep:file.txt
byl1-rep2
l2
git commit -am "conflict resolution"
git rebase --continue
, and Git then attempts to replay the "B
->C
patch" on top of commit E
... and succeeds! That patch applies cleanly; because the contents of file.txt
in commits B
and E
are identical, there is no cause for any conflict here, and you end up with