Forks, pull requests and review workflows
Fork versus branch models, syncing with upstream, protected branches and required checks, review etiquette, and rewriting a branch that is under review.
Fork or branch
# fork model: you have no write access to the upstream repository
git clone [email protected]:you/project.git
cd project
git remote add upstream [email protected]:org/project.git
git fetch upstream
git switch -c fix/timeout-handling upstream/main
# ... make the change ...
git push -u origin fix/timeout-handling
# then open a pull request from you:fix/timeout-handling into org:main
# branch model: contributors already have write access
git switch -c fix/timeout-handling origin/main
git push -u origin fix/timeout-handling| Fork model | Branch model | |
|---|---|---|
| Write access | Not required on the base repository | Required |
| CI on a pull request | Runs on the fork; repository secrets are withheld by default | Runs with the repository's secrets |
| Syncing | Add upstream and fetch it | Fetch origin as usual |
| Typical use | Open source, external contributors | Teams and internal repositories |
Keeping a pull request reviewable
# keep your fork's main current
git fetch upstream
git switch main
git merge --ff-only upstream/main
git push origin main
# keep the feature branch current by rebasing it, not by merging main into it
git switch fix/timeout-handling
git rebase upstream/main
git push --force-with-lease
# what has changed since the reviewer last looked?
git log --oneline @{u}..HEAD
git diff origin/main...HEAD- Push to your own fork or your own branch; never push onto someone else's open pull request branch.
- A pull request is a conversation about a diff. Under roughly 400 changed lines gets real review; several thousand lines gets an approval and a hope.
- Protected base branches plus required checks enforce the rules. Reviewer discipline alone does not survive a deadline.
- Explain the why in the description, list what you tested, and flag anything you are unsure about — reviewers find fewer bugs when they know where to look.
- Review the code, not the author. Ask questions rather than issuing verdicts, and say which comments are blocking and which are preferences.
⚠️
Rewriting a branch under review invalidates every reviewer's local checkout. An announced force-push is fine; a silent one wastes an hour of someone else's day. Say what changed, and use
--force-with-lease so you cannot overwrite a teammate's commits by accident.Stacking pull requests
# a stack: three dependent pull requests
git switch -c part-1/schema main
# ... PR #101 opens against main ...
git switch -c part-2/api part-1/schema
# ... PR #102 opens against part-1/schema ...
git switch -c part-3/ui part-2/api
# ... PR #103 opens against part-2/api ...
# after part-1 is rebased, move the branch above it onto the new base
git rebase --onto part-1/schema old-part-1 part-2/api- Target each pull request at the branch below it, then retarget to
mainas the ones underneath merge. - Keep most stacks three or four deep. Beyond that, one branch with well-separated commits is easier for everyone to follow.
- A squash merge creates a new commit, so any branch stacked on top must be rebased onto the updated
mainafterwards. - When a stack gets confusing, the fallback is one branch and a commit order that tells the story — reviewers can read commits one at a time.
FAQ
How do I review someone else's fork locally?
Add their fork as a remote (
git remote add contributor [email protected]:them/project.git), fetch it, then check out their branch and run it. Remove the remote afterwards so stale copies do not accumulate.Should we squash every pull request?
Squashing gives a linear main branch and one commit per feature, at the cost of the intermediate history. It suits small teams merging quickly; teams that later bisect regressions sometimes prefer the real commits. Pick one policy and apply it consistently.
Related
Tags, releases and semantic versioning Clean history: interactive rebase, squash and amend
Last refreshed 2026-09-18.