Search code examples
gitgithubmergesquash

Git erroneous no-op merge


I'm seeing a weird merge-failure in Git following a "squashed" merge-to-master.

I've created a tiny GitHub repo to reproduce the issue.

Essentially, the process is as follows:

What's going on here? Why doesn't the merge from master back into the branch include the change made directly to the master branch? Is this a bug or a use-error?


Solution

  • This is not a bug. The problem is that your squash commit is not a merge, so git doesn't know that it is connected to Branch-1. It sees it as an ordinary commit. When you merge master into Branch-1, git sees that there were following changes since those branches diverged:

    • in master: added file1 and file2, then deleted file1. Overall diff: added file2.
    • in Branch-1: added file1, added file2. Overall diff: added file1 and file2.

    Git merges branches using those overall diffs. You added file2 in both branches, but there is no merge conflict, because file2s from both branches are identical. So the outcome of the merge is a commit, containing both file1 and file2.

    For the same reason your pull request will add file1 to master.

    But if you've done a real merge instead of a squash, the result would be as you expect.


    Actually, this is even mentioned in git help merge:

    With the strategies that use 3-way merge (including the default, recursive), if a change is made on both branches, but later reverted on one of the branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the merge base are considered when performing a merge, not the individual commits. The merge algorithm therefore considers the reverted change as no change at all, and substitutes the changed version instead.