This is the difference between distributed VCSes and centralized ones like svn.
When I create a change/feature it usually ends up being separated into multiple commits--usually some generic feature change somewhere followed by the specific changes for whatever I'm doing. In the centralized world I'd just work in my directory for a week and then go through and parse out the changes and check them in (generic first, then specific).
With git I can check them in early but not push them. They exist as living breathing patches while I work on it. I'll amend and rebase them like crazy. After everything is tested and working I push the set up to the main repo so others can get at them.
The important thing is that you don't amend/rebase the main repo. That is messing with history and is annoying to anyone who already grabbed the original changes. But messing with your local repo isn't rewriting history--it's not history yet. It's a set of changes that are still in progress.
It's not like there are clean independent commits just floating around in there with the junk. It's the amalgamation of the junk that produces the clean commits, thus the need for rebase. As someone else in this thread talked about, being able to tweak my commit history has changed the way I've approached coding. I commit often because I know I'll be able to go back and rewrite history before other people have a chance to look at it.
I'm just asking, why can't you make a new branch and merge-commit every 3rd commit to it, with a better message? It would preserve the philosophical "involatility" of history.
Ok, so the philosophical "involatility" is preserved, sure, but that's rather a large amount of work to do to preserve unworkable deadends and silly commit messages and broken builds and the like.
Also, it introduces a huge non-linear mess into the commit history that can be hard to untangle. Just looking at topic branches in a normal tree with gitk can be hard. Can you imagine looking at topic branches and these junk branches at the same time?
You can just create a new branch before you start the rebase, which achieves exactly the effect you ask for. Rebase is how you "create a new branch with only the clean commits".
But, most of us don't bother copying before rebasing. The reflog makes that pointless from a safety perspective and, without the safety need, there's not much reason to copy before rebasing.
Also, I almost always work on topic branches and do my rebasing there. This may be a crucial point that others have missed. Personally I don't rebase on master.
Why not? The end result is exactly the same. You have a little branch of your work and then when you pull next time it gets merged back in. You can even create a named branch for it after the fact by sticking the hash into .git/refs/heads.
Well, then why not take the same care and simply create a new branch with only the "clean" commits, and then push that branch?
I don't see a need for rebase. Don't rewrite your existing history, make a new branch to push to others! Like "tags" in svn.