Why a scheduled merge should pin the commit you approved

Imagine you review a pull request at 5 p.m. and schedule the merge for 11 p.m. At 10:50 someone pushes one more commit to the branch. A naive scheduler merges whatever is on the branch at 11, so code nobody reviewed goes live.

Why branch protection alone may not save you

Some repositories dismiss approvals when new commits arrive, and some do not. Check your branch protection setting that dismisses stale approvals when new commits are pushed. If it is off, or if the person pushing can approve their own work, the merge can still go through.

The fix: merge only if the head is what you reviewed

GitHub's merge API accepts an optional sha value. When it is given, the merge goes ahead only if the pull request's head commit matches it; otherwise the call is refused with a conflict error. A scheduler that records the head commit when you schedule, and passes it when it merges, cannot merge anything else.

What a good scheduler does when the head changed

Other checks at merge time

How Merge Scheduler does it

Merge Scheduler records the head commit when you schedule, re-runs the prechecks right before merging, and passes the commit to GitHub when it merges. If the head changed, the release is skipped and the reason is shown on the release page and in the email.

Related: How to schedule a GitHub pull request merge (4 ways) · Releasing outside business hours: a checklist for small teams