Pull requests & code review
Lifecycle, reviews, CODEOWNERS, merge methods, the merge queue, status checks, discussions, and wikis.
Lifecycle#
A pull request tracks a source branch merging into a target branch, both within the same repository (cross-repository/fork pull requests target the upstream repository the fork was created from). State transitions (OPEN → MERGED / CLOSED) are recorded with timestamps and the actor responsible, all audit-logged.
Reviews#
Reviewers can leave a review in one of three states — Approve, Request changes, or Comment — plus inline comments anchored to a specific file and line of the diff, threaded for replies. A "Request changes" review blocks merge if branch protection requires resolving all review threads or a minimum approval count; re-requesting review after new commits is manual, not automatic, so stale approvals from before a force-push aren't silently trusted unless the repository's protection rules say otherwise.
CODEOWNERS#
A CODEOWNERS file (repository root, .github/, or .khub/) maps gitignore-style glob patterns to owners:
*.go @backend-team
/apps/web/ @frontend-team @jane
/packages/database/ @data-teamPatterns support * (any characters except /), ** (any characters including /), and a leading / to anchor the pattern to the repository root instead of matching at any depth. For each changed file, every rule is evaluated in file order and the last matching rule wins — identical semantics to GitHub's CODEOWNERS, so an existing file can be copied over unmodified. Matched owners are automatically requested as reviewers when the PR is opened (or when protection with "require code owner review" is turned on for an already-open PR).
Merge methods#
Configured per repository (allowedMergeMethods); a PR only offers the methods the repository allows, and merge eligibility additionally checks the repository's allowed-merge-roles list against the actor's effective role rank (see Authorization & permissions). Each method is real git plumbing executed server-side against a temporary clone, then pushed back through the same protected git push path as anything else:
| Method | Equivalent to |
|---|---|
| Merge commit | git merge --no-ff origin/<source> -m "<message>" — always creates a merge commit, preserving full source-branch history. |
| Squash | git merge --squash origin/<source> followed by a single git commit — collapses the entire PR into one commit on the target branch; the source branch's own history is untouched. |
| Rebase | The source branch is rebased onto the current target branch tip, then fast-forwarded into the target (git merge --ff-only) — replays the PR's individual commits on top of target with no merge commit. The rewritten source branch is also force-pushed back, so the PR branch's history matches what actually landed. |
A merge conflict aborts cleanly (merge --abort / rebase --abort) and surfaces as a normal error asking for manual conflict resolution — KHUB does not attempt automatic conflict resolution for any method.
Merge queue#
For a branch that gets a lot of concurrent pull requests, Add to merge queue replaces "everyone spams the merge button and hopes" with a serialized, automatic process: queued pull requests for the same target branch merge one at a time, in the order they were queued, with a background scheduler (checking every 30 seconds) that:
- 1waits for that PR's own CI run to actually finish and pass (not just whatever it was at the moment it was queued),
- 2re-checks the queuer's merge permission and the branch's protection rules against their current state, since either can have changed while the PR was waiting,
- 3performs the merge using the exact same code path a manual merge would, and
- 4on success, notifies whoever queued it and immediately starts processing the next entry for that branch — or, on failure (CI regressed, a permission changed, the PR was closed), removes the entry, notifies the queuer why, and moves on rather than blocking everyone behind it.
Queue position is scoped per (repository, target branch), so unrelated branches queue and process independently. Anyone can view a repository's queue; only the person who queued an entry (or a site admin) can remove it early.
Status checks#
Pipelines report per-job (and overall) status back onto the commit; branch protection can require specific named checks (matched by job name) or simply "CI must pass" before merge is permitted, independent of review state.
Discussions & wiki#
Repository Discussions are open-ended threads not tied to a specific commit range or issue — for design conversations, RFCs, or Q&A. The Wiki is a separate, versioned collection of Markdown pages per project, rendered with the same Markdown pipeline as everything else in the app (GitHub-Flavored Markdown via remark-gfm, sanitized on render).
