---
title: "GitHub PR Workflow"
slug: "github-pr-workflow"
category: "tooling"
tags: ["tooling", "github", "pull-requests", "code-review", "git", "workflow", "conventional-commits"]
status: "stable"
last_updated: 2026-05-14
summary: "Conventional Commits titles, squash merge defaults, auto-merge, CODEOWNERS routing, draft PR norms, and reviewer etiquette for a low-friction PR process."
related: ["[[tooling/github]]", "[[tooling/github-branch-protection]]", "[[tooling/github-actions]]", "[[tooling/github-secrets]]", "[[tooling/github-cli]]", "[[coding/git]]", "[[howto/deploy-quartz-site]]"]
---

## Overview

A pull request is the handoff point between a branch and `main`. A well-run PR process produces a legible `main` history, clear reviewer responsibility, and no surprise regressions. A poorly run process produces a log full of "fix", "wip", and "update stuff" commits with no trail for debugging. This page covers the mechanics of a PR from open to merge. Read [[tooling/github]] for the branching model and [[tooling/github-branch-protection]] for the rules enforced on `main`.

## Use Conventional Commits for PR titles and squashed commit messages

Every PR title follows the [[glossary/conventional-commits|Conventional Commits]] format because the squash-merged title becomes the commit message on `main`.

```
feat(tooling): add GitHub CLI cheatsheet
fix(ops): correct CNAME plugin path for custom domain
chore(deps): bump actions/checkout to v4
docs(coding): add Python typing page
```

The type signals intent: `feat` for new behavior, `fix` for bug corrections, `chore` for maintenance, `docs` for documentation, `refactor` for structural changes with no behavior delta, `test` for test-only changes. The scope names the area of the codebase. Keep the summary under 72 characters. See [[coding/git]] for the full commit message rules.

## Squash merge by default; preserve history only when it earns it

Configure the repository to default to squash merge and disable the other strategies to prevent divergent team behavior. Squash merge collapses a branch into one commit on `main` with the PR title as the subject.

Use merge commits only for long-running branches where the individual commits carry meaning worth preserving in the mainline log. That scenario is rare. A branch alive for less than a week earns a squash.

Disable rebase merge to avoid a three-way split between merge, squash, and rebase that confuses contributors about what history will look like after they click the button.

## Open PRs as drafts; promote when CI is green

Open the PR as a draft on the first push. This signals "in progress" and prevents reviewers from starting a review that will change. Promote to ready when all CI checks pass and the description is complete.

A ready PR description has two required sections: a summary of what changed and why, and a test plan the reviewer can follow. The test plan is a checklist. "Manually tested" is not a test plan; "Opened `/tooling/github-actions` and verified all links resolve" is.

Link the issue the PR closes with `Closes #123` in the description body. GitHub closes the issue automatically on merge. If no issue exists for a trivial change, skip the link; do not create a placeholder issue.

## Route reviews with CODEOWNERS

Create `.github/CODEOWNERS` to map file paths to required reviewers. GitHub adds the matching owners as required reviewers when a PR touches those paths.

```
# Whole repo default
*              @org/core-team

# Ops files require a second ops owner
/content/ops/  @org/ops-team

# CI workflow changes require a CI owner
/.github/      @org/devops-team
```

CODEOWNERS entries are evaluated top-to-bottom; the last matching rule wins. Keep the file short. Routing every directory to a different team creates overhead that slows merges without improving review quality.

## Enable auto-merge for PRs that are ready and fully green

Auto-merge merges the PR automatically as soon as all required checks pass and the required approvals are met. Enable it on PRs that represent complete, approved work waiting on CI.

```bash
gh pr merge --auto --squash
```

Auto-merge is safe when [[tooling/github-branch-protection]] enforces required status checks and required reviewers. Without those guards, auto-merge merges a PR the moment it is approved, regardless of CI state.

## Review code, not authors; approve only when confident

A PR review is a code read, not a social transaction. Approve when you have read the diff and believe it is correct, complete, and maintainable. Comment on lines you have questions about. Request changes when you see a bug, a missing test, or a design choice that needs discussion.

Avoid approving with comments that imply the code needs changes; that puts the author in an ambiguous state. Either request changes or approve and trust the author to address your comments before merge.

A "ship it" comment with no code read is noise. A short "LGTM, the cache key hash is correct, one nit on the comment in line 42" is useful.

## Related

- [[tooling/github]]
- [[tooling/github-branch-protection]]
- [[tooling/github-actions]]
- [[tooling/github-secrets]]
- [[tooling/github-cli]]
- [[tooling/github-releases]]
- [[coding/git]]
- [[howto/deploy-quartz-site]]
