As far as I can tell the only real difference is the existence of a develop branch in git-flow that allows integration testing before a batch release.
For example, when I'm on branch Feat-A, but I want to make a change related to Feat-B (or I already have but haven't committed), I'll stash my changes, merge Feat-A into dev, merge dev into Feat-B, pop my changes off the stash, and commit.
The whole switch goes:
- "Oops, these changes don't go on this branch"
- git stash
- git checkout dev
- git merge Feat-A
- git checkout Feat-B
- git merge dev
- git stash pop
It takes half a minute, but it keeps my branches clean, and lets me move from feature to feature at will. I may add a 'git oops' alias just for this process.
I.e. I just started learning Rails, building a new app from scratch, and you can imagine it becoming messsy. Before I get confident in a certain architecture, I would just push to master all the time with "some more blah" messages.
I think rebasing can be valuable in this sense, since it will destroy crappy history. I'm more found of the git flow workflow in a team development effort, expecially if your thingy is already in a production pipeline. I've found rebasing to be often very confusing and destructive, while merges are clear and easy to manage.