I have two branches B and A . B is the base of A . A1 is the first commit of A. Then I have several commits A2, A3, A4 and two merges back to B as shown below :
B1 ---------B2----------- B3 (Branch B)
\ / /
A1----A2-----A3-----A4 (Branch A)
Thing is that I am getting a merge conflict on merging A4 back to B(B3) . How can this be possible ? This is supposed to be a fast forward merge .
Potential hint
A4 is a commit from a feature branch, whose history is :
- checkout from A2
- Commit something
- Commit something else
- Merge A (to get latest changes aka A3)
- Merged to A thus creating A4
Could it be the case that command number 4(merge A) caused this issue because it was a merge and not a rebase , and if yes how ?
CodePudding user response:
A fast-forward merge requires the tip of one branch to be an ancestor of the other.
If we look at your diagram, before the merge:
B1 ---------B2 (Branch B)
\ /
A1----A2-----A3-----A4 (Branch A)
Note that there is no path backwards from B2 (the tip of branch B) to A4; nor is there any path backwards from A4 (the tip of branch A) to B2. So neither git switch A; git merge B
; nor git switch B; git merge A
can result in a fast-forward merge.
To put it a different way: if we moved branch A to commit B2, we would lose commits A3 and A4; if we moved branch B to commit A4, we would lose commit B2. So we need to create a new commit which has both A4 and B2 as parents, and move a branch pointer to that.
You even show this yourself, by adding a commit B3:
B1 ---------B2----------- B3 (Branch B)
\ / /
A1----A2-----A3-----A4 (Branch A)
A fast-forward merge does not create any new commits, it just moves branch pointers. For instance, if we instead start with this (where A2 has A1 and B2 as parents):
B1 ----- B2 (Branch B)
\ \
A1---- A2-----A3-----A4 (Branch A)
Here, B2 is an ancestor of A4, so git switch B; git merge A
can result in a fast-forward merge, giving this:
B1 ----- B2
\ \
A1---- A2-----A3-----A4 (Branch A, Branch B)
As you say, no conflict is possible in a fast-forward merge, because no changes are being applied; there's just a change in how existing commits are labelled. But your merge wasn't a fast-forward, so there is always a possibility of merge conflicts.