1

I did a merge the other day:

  1. I opened a pull request on GitHub
  2. I clicked the merge button on GitHub
  3. GitHub told me that there were conflicts, so I followed their instructions:
    1. git checkout A
    2. git merge B
    3. git checkout B
    4. git merge --no-ff A
    5. git push origin B

Afterwards, I realised that branch A was successfully merged into the branch B.

But when I switched back to branch A I realised that the branch B got merged into the branch A as well.

Why is that happening?

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
kaizer
  • 490
  • 1
  • 6
  • 17
  • Are you certain that you were the only one working at the time? – Tim Biegeleisen Mar 29 '18 at 10:40
  • @TimBiegeleisen yes, I was. To make sure i did a *git log* and only me was in the last 5 commits it happened before, to me and to others in the team, that's why now I would like to know why it's happening, it's really strange – kaizer Mar 29 '18 at 10:54
  • How did you perform your merge? – ChrisGPT was on strike Mar 29 '18 at 12:16
  • @Chris normal merge, after a PR, review, resolve conflicts, and merge – kaizer Mar 29 '18 at 12:32
  • 2
    @kaizer, what does "normal merge" mean? `git checkout B && git merge A` locally and then push? Something in a graphical client like SourceTree? Clicking the "merge" button in GitHub's Pull Request UI? You mentioned conflict resolution: what were the conflicts, and how did you resolve them? We can only make wild guesses at this point… – ChrisGPT was on strike Mar 29 '18 at 13:45
  • @Chris by normal I mean, open a PR on github,click merge button on Github, conflicts appear, follow Github instruction to resolve: *git checkout A; git merge B; git checkout B; git merge --no-ff A; git push origin B* PR resolved on github. branch A, is never pushed, the changes are dropped, so the local based is ok as expected and then you are asked to pull on the next push and then the mystery happened – kaizer Mar 29 '18 at 20:26

1 Answers1

2

Let's take a look.

You have two branches, A and B, and merging them generates conflicts. That might look something like this:

*---*---*---* [A]
     \
      *---*   [B]

You create a pull request on GitHub to merge B into A (or A into B, it doesn't really matter in this case). GitHub tells you that the merge generates conflicts that must be resolved and therefore can't be done automatically.

Following GitHub's instructions you run the following commands locally:

  1. git checkout A
  2. git merge B
  3. Resolve conflicts and complete the merge

Now your local copy looks something like this:

*---*---*---*---x [A]
     \         /
      *-------*   [B]

Here x is a new commit that resolves the conflict between A and B. Then you run the following commands:

  1. git checkout B
  2. git merge --no-ff A

Since x is a new commit not already included in B (and especially since you've included --no-ff) this generates a new commit y:

*---*---*---*---x   [A]
     \         / \
      *-------*---y [B]

Another option to resolve the conflicts without creating this "circular merge" is to rebase B onto A and resolve the conflicts that way:

  1. git checkout B
  2. git rebase A
  3. Resolve conflicts and complete the rebase

This generates something like

*---*---*---*         [A]
             \
              o---o   [B]

The two newest commits in B marked as o are new (their hashes have changed) so you'll have to force push B back to GitHub using --force-with-lease, but now you can complete the merge using GitHub's pull request UI without creating a "circular merge".

Make sure to read about the implications of rewriting commits and force pushing (o here) before doing this, especially if you work on a team.

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
  • Thanks for the time taken to explain, really appreciate it. And actually as I was typing earlier, I realised where the circular merge could come from. I suppose, even without pushing the commit **x** as it's in the commit **y** as a merge of B to A, it where the circular merge comes from actually I am just surprised/amazed that even without pushing the commit **x** it's present – kaizer Mar 29 '18 at 23:19
  • and actually I didn't do a rebase, because actually, the commands are from Github, they suggest the commands to use to resolve the merge. next time will try the rebase see if it does that again – kaizer Mar 29 '18 at 23:20
  • @kaizer, when you push branch `B` all commits in that branch get pushed. That includes commit `x`, thanks to the merge of `A` into `B`. – ChrisGPT was on strike Mar 29 '18 at 23:25