In the past I've encountered the scenario where a single git rebase
resulted in me having to resolve the exact same conflict multiple times.
To better understand the preconditions needed to cause this scenario, how can I create a minimal example that recreates this scenario (where I have to resolve the same conflict twice)?
e.g.,
$ git checkout feature-branch
$ git rebase master-branch
CONFLICT (content): Merge conflict in my-file
(manually resolve the conflict in my-file)
$ git add my-file
$ git rebase --continue
(get the exact same conflict in my-file again)
CONFLICT (content): Merge conflict in my-file
(I seem to recall I had a suspicion that the scenario I encountered had merge commits in feature-branch and/or master-branch and that was a precondition for the repeating conflict)
CodePudding user response:
git-rebase
brings up merge conflicts per commit instead of per branch. So something like this should work:
git init
echo 'stuff' > file
git add file
git commit -m"Initial commit."
git checkout -b branch
echo 'different stuff' > file
git commit -m"First branch commit."
echo 'entirely different' > file
git add file
git commit -m"Second branch commit."
git rebase origin:master
CodePudding user response:
Let me know if this is what you mean by "the same conflict":
git checkout -b basebranch
echo test 123 > file.txt
git add file.txt
git commit -m1
git checkout -b feature
echo test 456 >> file.txt
git add file.txt
git commit -ma
# edit the file in an editor and change the second line from 456 to ABC
git add file.txt
git commit -mb
git checkout basebranch
echo ------ >> file.txt
git commit -amhyphens
git checkout feature
git rebase basebranch
If on the first conflict you resolve the conflict and put 456 after -----, when it applies your next commit it is still going to want to change 456 to ABC after a line that says 123 not after ---- so you will have to help git out again
Here is the first conflict:
$ git diff
diff --cc file.txt
index 2ee3b312b4,f28dd71184..0000000000
--- a/file.txt
b/file.txt
@@@ -1,2 -1,2 1,6 @@@
test 123
<<<<<<< HEAD
------
=======
test 456
>>>>>>> a
then if you resolve that
test 123
------
test 456
putting test 456
after the line of hyphens... and continue
git add -A
git rebase --continue
$ git diff
diff --cc file.txt
index 7329ce6fb4,acef073ce8..0000000000
--- a/file.txt
b/file.txt
@@@ -1,3 -1,2 1,7 @@@
test 123
<<<<<<< HEAD
------
test 456
=======
test ABC
>>>>>>> b
because it is expecting the test 456
-> test ABC
change to come after the line test 123
, but it finds the line of hyphens and isn't sure that the change is still applicable.. or doesn't know how to make the change... or something.
so again you have to help it out.
test 123
------
test ABC
a couple comments about this:
- One "mistake" a lot of people make in a rebase like this is that.. if they know how the final code should look, they put the final answer in to an earlier commit... so for example... when you hit the final former conflict, you know that you have finally decided to put
ABC
not456
, so you just put in the final answer.. instead of answering the question 'How can I apply this change in the new context?', people sometimes answer 'What should go here?' which can also lead to conflicts when applying later commits that are even harder to understand - In some cases, if you don't care about the details in the feature branch, and would like to squash them all anyhow, it is helpful to squash the feature branch before rebasing against the basebranch.. then you only have to resolve the conflicts once:
git checkout feature
git rebase HEAD^^^ -i
# or
git rebase $(git merge-base HEAD basebranch)
- having to resolve two conflicts isn't necessarily a problem that needs to be avoided. If each commit you are applying matters, taking a second to think how to apply that change in the new context is sometimes exactly what you want to do. Solving the initial conflict (deciding how to apply commit 'a' given the changes to the base branch) does not tell you how to apply commit 'b'. that's a new question. You are the only person who knows how the
456
->ABC
(b
) change should be applied given the line of hyphens that you have added, and having told git how to apply the initial456
change (a
) doesn't change that.