If a strategy requires humans to be virtuous AND vigilant it is doomed to failure.Sorry, but I don’t buy that. By the same principle, there’s also no point in writing unit tests or defining static types or having code reviews, all of which require thought and extra work, yet can yield considerable dividends when done even moderately well.
I rarely use history and prefer merge/squash, with automated CI tools, and tests. "Why" is kept in doc strings, comments, specs, and story tickets.
The argument for a tidy history isn’t just about a different place to explain a change. It’s about presenting work in clearly defined, meaningful steps to other readers like code reviewers, or perhaps someone who found these commits later through `git blame` on a problematic line of code or `git bisect` after a regression. It’s about each commit representing a complete, self-contained change that could later be reverted, or cherry-picked or merged to another branch.
I submit that, if your code is so complex that diagnosing a bug is a major research project rather than moving forward with a few extra/modified lines of obvious fix, then that is the problem to focus on.
Some problems have a lot of essential complexity. The code to solve them necessarily has at least the same degree of complexity. Sooner or later, there will probably be a change to that code with an unintended consequence for something else. Keeping the code and its history tidy and systematic is, IMHO, how you avoid those investigations becoming major research projects.