Why wouldn't you use a local branch (or something?) for your ugly commits and then merge everything from that branch into the main shared branch when you're done?
I am doing a lot of exploratory programming and way point commits.
I don't need the reviewer to understand all the mistakes I made and bad designs I considered. It's enough work to understand the finished design.
As a rule of thumb, every commit that lands in master's history should build and pass tests. So that eg 'git bisect' works.
But it's not a good idea to put that same requirement on waypoint commits I make along the way, when exploring.