A typical workflow for me:
$ git commit -a -m "WIP" # picture this, but 100 times as I go
$ git reset $(git merge-base main HEAD) # Reset to the merge-base to avoid reverting upstream work
$ git diff # Get a nice overview of everything I've changed, to aid in crafting a nice commit message
$ git add .
$ git commit # Type up a nice commit message describing the whole change
Contrast this with using `rebase -i` to squash: $ git commit -a -m "WIP" # picture this, but 100 times as I go
$ git rebase -i $(git merge-base origin/main HEAD) # rebase to the merge-base because I don't want to deal with merge conflicts yet
$ # search/replace 'commit' with 'squash' in a text editor
$ # save/quit
$ # get prompted for new commit message, type it out
$ # save/quit
They both feel like the same amount of typing to me, but `rebase -i` thrashes my working tree around with each commit, which has a habit of confusing my IDE quite a bit and breaking its build cache. Also, I like the `git diff` step in the reset workflow because it gives me a nice reminder of what my change looks like, which helps inform how I should word my commit. So I use reset.If I want to keep my intermediate work locally for posterity, I usually use `git branch prprep/<bug_number>_unsquashed` or something so that I can dig it up later if need be. I don't push any of my `prprep/` branches.
Bingo. I do this all. the. time. I don't want anybody seeing it. I honestly couldn't imagine another way of working... commit early, commit often, I say. Hell, commit on a timer every minute, if that's your thing (I've never done this but totally understand people who do.) Leave the meaningful messages for later when you're actually ready to craft a PR.
Honest question: if you avoid committing code unless it's working and you have a meaningful message to make, what happens if you screw up your editor undo, and you need to go back to where you were 10 minutes ago? This happens all the time for me... I undo a whole bunch and then accidentally type the "z" button into my buffer because I fumbled the keyboard, and now I can't "redo" back again. If I commit early and often, I can recover the work to where it was, even if it's not compiling yet. If I have to wait for my code to be basically "reviewable", I'd be screwed.
And the WIP commits can still be done, but locally. Then I clean them up everytime I push to the remote branch, but not when that branch is merged.