First time I encounter a Git behavior which, on first look, seems to defy common sense.
1. create a feature branch off master
2. perform some changes and commit (in this example – add a new line to foo.c)
3. merge the changes to master using a pull request with squash
4. on the feature branch, revert the previous commit (in this example – remove the line from foo.c)
5. merge master to the feature branch
One would expect that the reverted content will remain or that at least a manual merge conflict will occur. But surprise – the merge overrides them with the content on master (the content before the revert).
So why it happens? because how three-way merge works when there is a single common ancestor.
In the diagram, you can see that C1 is the common ancestor of C3 and C4. When doing the merge, git compares C4 to C1 and C3 to C1.
Since C1 and C4 are identical, it causes git to “understand” that the feature branch did not change the file at all, so it should take the change introduced in C3 and apply it as the merge result.
How it differs from a regular (non squashed) merge?
In this case, the common ancestor changes. It is now C2. So git compares C2 and C3, find that they are identical, hence selecting the change between C2 and C4 as the “interesting” change to apply as the merge result.
Conclusion: if you merge with squash, do not use the same branch to introduce additional changes…