Ideally, each commit should be something that you could submit as a stand-alone patch to a mailing list; whether it's a single commit that was perfect from the get-go or fifty that you had to re-order and rewrite twenty times does not matter at all; the final commit message should contain any necessary background information.
It would be needlessly restrictive to prevent users from making intermediate commits if that helps their workflow: I want to be able to use my source-code management tool locally in whichever way I please and what you see publicly does not need to have to have anything to do with my local workflow. Thus, being able to "rewrite history" is a necessary feature.
Indeed they are, hence the need to rewrite the history. Managers, tech leads, or users of your OSS project don't care about the "fix typo" comments. They are interested in a meaningful history that tells a bigger story.
And to be frank, I am interested in the same, mid-term and long-term. While I am grappling with a very interesting problem for a month then yes, I'd love my messy history! But after I nail the problem and introduce the feature I'll absolutely rewrite history so the squashed PR commit simply says "add feature X" or "fix bug Y".
Why would they be looking at the version control system for this? That is not what it's there for.
And many tech leads simply don't have the time to review every single WIP commit. They want meaningful message/description of the big squashed PR commit. If you just post a merged list of all commit messages with 10x "fix stuff" inside you'll be in big trouble the next time around and your work will be inspected very closely.
The practices I am describing to you are reality in many tech companies. Writing code there is not about you at all. And almost nobody will read your code and PR descriptions unless they really have to. Hence it's a professional courtesy to make those as small and meaningful as possible.
Do you usually review every commit? I usually just review the diff between the PR'd branch and master, as does everyone I work with.
Whether you think that "makes no sense" is inconsequential. Many people find it very meaningful.
Let alone the code review issue. In any multi-person project, it is just as important that your commit history be readable by a third party for information as that it be useful for your own personal debugging.
Compromises with human nature must be made. Hence -- we need to be able to rewrite history.
Your academic purism is out of place, dude. Real humans don't work like you say they do. Some do -- most don't.
By definition the actual history of your work includes WIP, so this means your commit history should not reflect the actual history of your work.
Just don't publish WIP crap; fortunately, you can have your cake and eat it too, with git.
The biggest reason git (and any similarly advanced SCM) is superior to non-distributed alternatives like Subversion is that I can use it to manage my own workflow, instead of just as the final off-site backup of whatever I decide to publish. I get to actually use everything git offers for shuffling commits and code around while coding.
Want to switch contexts quickly? git commit the whole thing and just switch a branch.
How about untangling a hairy merge? Do it piecemeal and commit when you're done with each bit; it's trivial to then undo mistakes, redo, combine or reorder stuff and you cannot lose any work by accident because git commits are immutable.
All of these features essentially require history rewriting; sure, you're free to rebrand and not call "store WIP state in repository" a commit even though it is one, but I would consider any SCM without these features nigh useless for most work.
Why?
But it absolutely should when you work in a team. I'll personally scold you if you waste my time with merging a 20 commit PR of which 10 commmits are "fix stuff" or "fix typo" or "oops forgot variable" etc. It won't pass code review.
You are free to disagree. I am only telling you how it is in many companies.
2. Waste of later coders' time when running git blame on a line when trying to figure out the purpose of code
3. Waste of later debuggers' time when they need to decide whether this error is the thing they're looking for, an unrelated error to bisect skip, or an unrelated error in possibly-related code that they need to manually fix and then re-test.