A Push Rejection Is a Discovery Made Too Late
The default sequence is: do the work, commit it, push it, find out whether the remote moved. That last step is where most of the pain lives, because by the time you learn the answer the commit already exists on a base that turned out to be wrong. Unwinding it is a manual operation, under time pressure, while holding a lock everyone else is waiting on.
Fetch first instead. Ask where the remote is before deciding what to build on, and four cases appear — each with an obvious correct action, and the fourth of which is to stop.
The Four Cases
Level or no remote branch. Build on the local tip. Nothing to reconcile.
Behind. The remote has commits you do not. Build directly on the remote tip rather than on your stale local one. This is the case that quietly produces "why did my change disappear" if you get it wrong, and it has one extra check worth doing: if the remote's new commits touched the same paths you are about to land, stop and reconcile by hand. Two writers editing the same material is not something an automated rule should resolve.
Ahead. You have local commits the remote does not. Build on the local tip, keeping them, and push the lot.
Diverged. Both sides have commits the other does not. Refuse. There is no correct automated answer — a merge might be right, a rebase might be right, and which one depends on facts the tool does not have. Stopping here is the feature.
Refusal Is a Result
An automated operation that stops and says "history diverged, a human should look at this" is doing its job. The temptation is to make it clever — try a merge, fall back to a rebase, force if the merge is trivial — and every increment of cleverness moves a decision that needed a human into a code path nobody will read until it does the wrong thing quietly.
The bar to apply: automate the cases where the correct action is determined by the state, and refuse the cases where it is determined by intent.
What is good about that criterion is that it shortens the argument. When somebody proposes automating one more case there is only one question: is the answer determined by this state alone? If it is, do it. If it is not, name the additional fact you would need. If the tool can hold that fact, give it the fact first; if it cannot, you have found where the refusal belongs.