5

I've just squash merged my entire develop history history into my master branch. As I see it that should connect both branches in the network graph, which it doesn't. Also, my master branch shows: This branch is 1 commit ahead, 151 commits behind develop., whilst I'd expect it to be even with develop after squash merging. Why is that not the case?

And how do I merge my changes into master from develop, in such a way that it's only one commit on master, it's even with develop (at that point) and connects in the network graph?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 1
    Possible duplicate of [git: why can't I delete my branch after a squash merge?](http://stackoverflow.com/questions/41946475/git-why-cant-i-delete-my-branch-after-a-squash-merge) – mkrieger1 Jan 31 '17 at 18:57

2 Answers2

6

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.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • 1
    So there's no way to create just a single commit on master for a version and have the branches be linked in the network graph? –  Jan 31 '17 at 18:59
  • @ismay Yes there is: a regular merge commit. – mkrieger1 Jan 31 '17 at 18:59
  • It seems to me that's a normal merge. Can you help me understand what you want that is different from a normal merge? – Mark Adelsberger Jan 31 '17 at 18:59
  • 2
    I'd say that what I like about squashing is that the commits from develop don't appear in the master branch commit history, just the new squash commit. For a detailed history you can consult the develop branch. –  Jan 31 '17 at 19:08
  • Well, I thought that might be the case; see my update – Mark Adelsberger Jan 31 '17 at 19:20
  • The main use-case for squash-"merge" (in quotes since it's not *a* merge, noun form, at all, as you note) is very short lived branches: make branch, make changes, commit, repeat until happy with result, decide that all N commits should be 1 single commit of "fix bug XYZ", do squash-merge, delete temporary branch. For longer-lived branches, I prefer real merges. Note that you can view the merge as an all-in-one diff using, e.g., `git show -m` on the merge, or `git diff ^ `. – torek Jan 31 '17 at 23:44
  • @torek - I've thought of that as a use case for rebase (possibly interactive so as to squash the commits); but I'll concede that using `merge --squash` is probably easier so long as you remember to discard the original commits afterward. – Mark Adelsberger Feb 02 '17 at 15:46
  • @MarkAdelsberger how can I fix my dev and master branch in this case where is after squashing is master behind develop? Thank you. – Jenan Jun 23 '18 at 06:41
  • @Jenan - A complete answer to that is to large for comments discussion (and isn't really part of an answer to this question). I have a partial answer at https://stackoverflow.com/questions/50953897/git-merging-in-reverse-direction-after-squashed-merge/50955776#50955776. The main limitation on that answer is a fairly reasonable expectation if we're talking about the `master` and `develop` branches in gitflow, but that may not apply to your case. So I suggest, if that won't work for you and a search doesn't yield a more complete answer, posting the question as a question – Mark Adelsberger Jun 25 '18 at 13:35
0

If you really want to go with this method you only have one way of merge back master into dev after every squash merge for the master not being behind the dev and you can continue to go with this method.

Sinandro
  • 2,426
  • 3
  • 21
  • 36