You're not looking at the possibility that someone may do a bunch of
development locally, then use rebase to clean it (the local changes)
up before pushing it out to a central repository (or merging it into
master). If you're really paranoid that someone will use rebase to screw up master, you can use a tool like gitosis or gitolite to manage permissions on a central repository. You can say that no one has permissions to push things to master that are not fast-forwards.
Scenario #1:
I'm working on a feature branch. I have a number of discrete changes
that I'm making. I attempt to keep each of these changes in its own
separate commit. After completing 10 such changes, I realize that I
introduced a bug in change 3. I commit the bugfix with the same
commit message title as change 3, but with a "squash!" prefixed at
the front of it. Now when I'm finished with my changes on the
feature branch I can run "git rebase -i". git-rebase will
automatically position the bugfix to change 3 next to change 3 and
set it up to be squashed into the change 3 commit. Then when I merge
my changes into master there are only commits for changes 1-12,
instead of 50 commits covering all of the minor bugs that I fixed
with my undeployed code.
Scenario #2: Rewriting commit messages. This is one that I use all of the time at
work. I use a commit message template that has "Reviewed-by: ???" at
the bottom. When I do all of be topic branch development, I don't
get someone to review each individual commit prior to commiting it
(as that would defeat the purpose of a DVCS... might as well go back
to SVN at that point and managing chunks of changes prior to commits
with something like `quilt`). So now all of my commit messages have
"Reviewed-by: ???" on them. Prior to merging the changes back into
master, I can use git-rebase or git-filter-branch to go back and
edit my history to change "Reviewed-by: ???" to "Reviewed-by: Bob"
on my commit messages.