Pull Requests
A pull request proposes merging one branch into another and wraps that proposal in review, status checks, and discussion. It is the unit of change review on GitHub — and it is a GitHub feature, not a Git one. Git has merge; the review, the checks, and the merge button around it are the platform.
Most of what distinguishes a smooth PR workflow from a painful one is choosing the right merge method and understanding what gates the merge button. Get those two right and the rest of the lifecycle — drafts, auto-merge, reverts — follows naturally.
The PR Model
A pull request points a head branch at a base branch and shows the diff between them. Opening one does not merge anything; it creates a place to review the proposed change. That separation from a raw git merge is the entire value — the merge is gated behind review and checks rather than happening the moment you run a command.
The diff a PR shows is computed against the merge base, so it reflects what your branch adds on top of base, not every commit that happens to differ. Keeping the base branch updated is what keeps that diff honest.
Draft Pull Requests
Marking a PR as draft signals work-in-progress: reviewers are not pinged, and required reviewers — including those set by CODEOWNERS — are not auto-requested until you mark it ready. It is the way to open a PR early for CI feedback without summoning reviewers prematurely.
The common confusion is wondering why CODEOWNERS reviewers were never requested on a draft. They are suppressed by design; requests fire when the PR transitions to ready for review, not before.
Merge Methods
GitHub offers three ways to land a PR. A merge commit keeps every commit and adds a merge node, preserving true history at the cost of a noisier graph. Squash and merge collapses the branch into one commit on base, giving a clean linear log but discarding the intermediate commits. Rebase and merge replays each commit onto base with no merge node, keeping the commits but rewriting their SHAs.
The right choice depends on the branch. A curated series of meaningful commits argues for merge or rebase; a branch full of "wip" and "fix typo" commits argues for squash, which is why squash is the common default.
Status Checks and Mergeability
The merge button is gated by required status checks, the absence of conflicts, and — if configured — being up to date with the base branch. A green check means CI passed; it does not mean the branch has seen base's latest commits, which is a separate gate.
Requiring "up to date with base" before merge catches semantic conflicts that a textual merge would not: two PRs that each pass CI alone can break when combined, and this gate forces that combination to be tested before either lands.
PR Lifecycle Mechanics
Auto-merge lands the PR the moment its required checks and reviews pass, so no one babysits the button. "Update branch" pulls base into the head branch to satisfy the up-to-date gate. After a merge the head branch can be auto-deleted, and a merged PR can be reverted with one click to generate a clean inverse PR.
Merge commit preserves every commit and adds a merge node, keeping true history but a noisy graph — choose it when individual commits matter. Squash and merge collapses the branch into one commit on base, giving a clean linear log but losing the intermediate commits — choose it for feature branches with messy WIP commits, which is the common default.
Rebase and merge replays each commit onto base with no merge node, keeping the commits but rewriting their SHAs — choose it when you want linear history and clean per-commit content. The SHA rewrite is why it is unsafe on a shared branch others have already pulled.
- Squash-merging a branch that another branch was based on, so the original commits never appear on base and the dependent branch shows phantom conflicts.
- Opening a PR from
mainof your own fork, so you cannot update it without polluting your default branch and future PRs collide. - Leaving a PR in draft and wondering why
CODEOWNERSreviewers were never requested — required reviewers are not auto-requested on drafts. - Force-pushing to a PR branch after reviews, which can dismiss approvals and lose reviewers' place in the diff depending on settings.
- Picking rebase and merge on a shared long-lived branch, where rewritten SHAs break anyone who already pulled those commits.
- Standardize on squash and merge for feature branches so the default branch log reads one line per change.
- Open PRs as draft until CI passes, then mark ready for review to trigger reviewer requests.
- Enable auto-merge so the PR lands the moment required checks and reviews pass, with no one watching the button.
- Require branches to be up to date with base before merge to catch semantic conflicts CI would otherwise miss.
- Use "Revert" on the merged PR to generate a clean inverse PR instead of hand-crafting a revert commit.
Knowledge Check
You have a branch with curated, meaningful commits you want preserved on base. Which merge method fits?
- Merge commit or rebase and merge — both keep the individual commits, unlike squash
- Squash and merge, since it always produces the cleanest result on the base branch
- Any of the three methods; they all preserve the original commits on base
- None — a curated commit series cannot be landed through a pull request at all
Why does squash-merging break a branch that was based on the squashed branch?
- The original commits never land on base, so the dependent branch still carries them and shows phantom conflicts
- Squashing the source branch automatically deletes any dependent branch that was ever based on it, wiping out the downstream work entirely
- The squash commit is created with no parent at all, so Git can never compute a diff against it
- It does not actually break anything at all; the dependent branch still merges back perfectly cleanly
What does marking a PR as draft suppress?
- Reviewer notifications and auto-requests, including
CODEOWNERSreviewers, until the PR is marked ready - Every CI status check configured on the branch, holding all of them back until the PR is finally marked ready for review
- The diff view itself, so that reviewers are unable to see any of the proposed file changes yet
- The ability to push any new commits to the head branch for as long as it stays in draft state
What is the consequence of rebase and merge on a shared, long-lived branch?
- The replayed commits get new SHAs, breaking anyone who already pulled the original commits
- Nothing at all — rebase and merge is completely safe on any branch whatsoever, whether shared with others or not
- It adds an extra merge node to the graph that needlessly clutters up the shared branch's history
- It silently squashes the whole branch down into one single combined commit on base
You got correct