Your branching model seems to require specifying --no-ff
on every merge, forcing bookkeeping entries even for empty merges -- for example in your graphic you'd do the merge from hotfixes to 0.2, which gets that one commit onto the master branch and doesn't actually do any merging, with git merge --no-ff hotfixes
. On projects with un-git-aware administrative requirements that's a good way to do it. VonC answered for the case where you skipped that model's --no-ff
requirement somewhere.
For the case where you did follow your model and just weren't expecting push
to behave as it does: if you checkout master as of 1.0 in a repo with your graphic's history and push to the remote's master branch, when the push completes the remote will have commits M2,M4,M5,Y1-6,G1-4,R1, and C1-3 (labeling its commits according to their color and vertical sequence), and the remote master branch will refer to all of that.
The thing to understand is that commit histories are important, but ref names are not, at least not "capital-I" important. git push
Updates remote refs using local refs, while sending objects necessary to complete the given refs.
Usually, if your repo is part of a project's primary development you're tracking some "central" repo's ref names. Git's default clone sets up local remotes/origin/* branches for those; but other setups aren't at all unusual — if you've got a repo where you're working on v2.1 of some project, you might regard some other repo's release-v2.1 branch as your repo's 'master' branch.
If you want to push only the results of a commit, without pushing its history, you have to make a new commit that has the results but doesn't have that history. Other dvcs's have been built by people who regard constructing histories this way with varying degrees of repugnance; git sees choices like that as none of its business: it provides (it is) tools that implement any model you care to imagine. git cherry-pick
will make a new commit by diffing the named commit against its first parent and then applying that diff to the current head, with the cherry-picked commit's message. Vanilla git rebase
picks an entire sequence of commits like that. The behavior I think you were expecting is what git merge --squash; git commit
does: apply the diffs in a commit's history and forget where they came from. If you do that, no commit from anywhere else will ever appear on your branch's history. That's definitely not the model your graphic is trying to convey.