Home > Enterprise >  Merge conflict in a fast forward merge
Merge conflict in a fast forward merge

Time:04-12

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 :

  1. checkout from A2
  2. Commit something
  3. Commit something else
  4. Merge A (to get latest changes aka A3)
  5. 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.

  • Related