Squash merging creates a new commit on "our" branch (master in your case) to bring in the changes of "their" branch (development) as though you had merged the two. It does not actually crate a merge (a multi-parent commit that ties the two branches together); if it did that would be just a regular merge. So git cannot afterward tell that the commits from development are equal to the new commit added to master.
I guess I haven't seen the right use case, but I find squash merges somewhat pointless. The worst of both worlds between merging and rebasing as far as I can see.
UPDATE - Some clarifications might help, based on comments...
So we know that a regular merge is a single commit with two or more parents. Its first parent is "our" branch (let's say master) from the merge, and the branches we merged in are the additional parents. That single commit is all that's added to master.
A ---- B - M
/
X ---- Y
So this may seem wrong because git log
will show A, B, X, and Y separately. This is the default behavior, because it shows you how the changes were truly introduced.
You can get a somewhat more linear view by saying git log --first-parent
, but still log
doesn't want to show a patch for a merge (meh) so it doesn't quite look like a linear history as you'd get from a squash or a rebase.
But certainly M^
is equal to B
, so from the master point of view M
is a single commit that introduces all changes from the branch. And if you want it to also record that the changes from X
and Y
are reachable from M
, then this is how git provides that.
Now you may have picked up that I don't like merge --squash
too much, so here's why:
Let's say I do a squash merge instead of the regular merge pictured above. For clarity I'll add a common ancestor O:
O ---- A ---- B ---- XY <--(master)
\
X ---- Y <--(development)
and now some more work happens on develop
O ---- A ---- B ---- XY <--(master)
\
X ---- Y ---- Z <--(development)
So how do I best go about merging Z into my master branch?
If I had done a regular merge of Z into master, then git would know that Y is the common ancestor of Z and M (but I don't have M; I did a squash so I have XY), and I could do another merge with no problem.
If I had rebased my development branch onto master, I'd have
O ---- A ---- B ---- X' ---- Y' <-- (master)
\
Z <-- (development)
which is also ok, so long as my rebase didn't mess up anyone else's history (as it probably would've if X and Y had already been published, but that's a whole other can of worms).
In both of those cases I can do another merge or rebase with no problem. But by doing a squash merge I've confused git into seeing two histories without a good recorded relationship between them, so unless I've kept a ref pointed at Y I'm out of luck
O ---- A ---- B ---- XY <--(master)
\
X ---- Y ---- Z <--(development)
^- (last_merge)
And, as you've noticed, git status
will be forever confused if you take this path.