为什么在我的rebase操作中只发生一次提交而不发生两次冲突? [英] Why does a conflict occur for only one commit instead of two in my rebase operation?

查看:68
本文介绍了为什么在我的rebase操作中只发生一次提交而不发生两次冲突?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 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 的修改行),因此我期望两个合并冲突:

  1. 当从 rep2 进行第一次提交时, line1-modified-rep1 vs line1-modified-rep2 行将发生冲突
  2. 将应用来自 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)在 git commit -am冲突解决"

您现在运行 git rebase --continue ,然后Git尝试在其顶部重播" B -> C 补丁"提交 E ...和成功!该补丁完全适用;因为提交 B E 中的 file.txt 的内容是相同的,所以这里没有任何冲突的原因,并且最终导致

I have rep1 repository with two commits on master branch. These commits have file.txt with the following content:

line1
line2

I clone rep1 into rep2 and checkout remote branch as tracking:

git checkout --track rep1/master

Then in this repository I modify first line of file.txt to be:

line1-modified-rep2
line2

Make commit. Then modify its second line to be

line1-modified-rep2
line2-modified-rep2

Make commit. So, here in the rep2 I have added two commits to master branch that tracks remote rep1/master branch.

Now I'm going to generate a conflict. On the remote 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

Ok, now we're all set for merge conflict. I push commits from rep2 to rep1, get rejected and when prompt for rebase select this option.

Now, I was reading that 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:

  1. when first commit from rep2 would be applied and the lines line1-modified-rep1 vs line1-modified-rep2 will get conflicted
  2. when first commit from rep2 would be applied and the lines line2-modified-rep1 vs line2-modified-rep2 will get conflicted

But there is only one merge conflict and upon its resolution I can successfully push my commits to the rep1. What am I missing here?

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:

A--D (rep1)
 \
  B--C (rep2)

Added screenshots of the resolution process:

So the resulting file after the conflict resolution contains these lines:

line1-modified-rep2
line2

This is a log of git commands recorded by phpstorm (origin is 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

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.

More details

For completeness, here is how to recreate a simplified version of your toy example from the command line; I've shortened the lines in 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

After all those commands, your rep2 repo looks as follows (the contents of file.txt is shown underneath each commit):

Now, in rep2, you run

git rebase rep1/master

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 "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:

Not knowing what to do, Git asks you to resolve the conflict, which you do by replacing the contents of file.txt by

l1-rep2
l2

(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:

git commit -am "conflict resolution"

You now run 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

这篇关于为什么在我的rebase操作中只发生一次提交而不发生两次冲突?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆