Review

Merging is the one irreversible thing, so it says no clearly

Every reason a pull request cannot merge is collected and shown together. Being sent round the loop one blocker at a time is the thing contributors hate most.

Three strategies, done properly

A merge commit keeps both histories. A squash produces one commit whose parent is the base, carrying the pull request title and the individual commit subjects as notes. A rebase replays each commit, so the branch keeps its shape.

  • All three run as git plumbing against the bare repository
  • No working tree is checked out to merge anything
  • A rebase replays commits rather than collapsing them

The rules a branch can require

Protected branches carry the gates, and each is checked before git is touched.

  • A number of approvals, optionally dismissed when the branch moves
  • All review threads resolved
  • Named checks reporting success on the current head
  • A linear history, which refuses a merge commit and allows squash or rebase

A push that arrives mid-merge is not overwritten

Every strategy ends in a ref update guarded by the branch's expected old value. If somebody pushed between the checks and the merge, the update fails and nothing is lost, rather than the merge quietly discarding their commit.

Changes requested outranks arithmetic

One reviewer asking for changes blocks the merge regardless of how many approvals sit next to it. Only the latest review from each reviewer counts, so an approval after a change request is a change of mind rather than a second vote.

Make the merge button mean something

The rules are pure functions with tests, so a rule that says no can be reasoned about.

Self-host ReviewOS All features