Home > Software engineering >  What is a minimal "git rebase" example where the same conflict reappears?
What is a minimal "git rebase" example where the same conflict reappears?

Time:11-27

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 gui with conflict; a text version follows this image

$ 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 gui showing conflict; text version of diff follows this image

$ 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 not 456, 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 initial 456 change (a) doesn't change that.
  • Related