Bad code usually does not survive because of one dramatic mistake. It survives because several small process failures line up: the diff is too large, the review is too shallow, and the checks are too easy to ignore.
Shrink the problem
- Keep pull requests small enough that a reviewer can hold the whole change in mind.
- Split unrelated cleanup from behavior changes.
- Land risky migrations separately from feature work.
Make risk visible
A merge process should surface the important parts of a change: permissions, data flow, error handling, and rollback impact. If those details are hidden in a giant diff, people miss them.
Use automation as a filter
- Run linting and tests before review starts.
- Flag changed files that touch security or payment paths.
- Escalate only the parts that need human attention.
What actually stops bad merges
The fix is not a single blocker. It is a system where the easiest path is also the safe path: smaller changes, better checks, stronger ownership, and clear review expectations.