Branches & Pull Requests for Teams
7 pages · ~5 min✓ Reviewed
Builds on Git Basics: Commit, Branch, Push. Next up: Resolving Merge Conflicts.
Branches and PRs: The Mental Model
1. Branch and PR Defined
- A branch is a movable pointer to a commit
- Creating one copies no files: cheap, short-lived by design
- A pull request asks GitHub to merge a head branch into a base branch
- The PR carries discussion, review and CI checks
bash
git switch -c feat/login-form
new pointer at the current commit
2. Feature-Branch Flow
- maindeployable
- Branch offfeat/...
- Commitsall work here
- PRreview + CI
- mainmerged
- main stays deployable: never commit straight to it
- The PR is the gate back into main
3. Naming and Size
| Pattern | Example |
|---|---|
feat/short-topic | feat/login-form |
fix/short-topic | fix/null-cart |
chore/short-topic | chore/bump-deps |
- Format:
type/short-topic, lowercase kebab case - Keep branches short-lived and small
Size rule
Under ~400 changed lines gets real review. A huge PR gets a rubber stamp.
Core Workflow: Branch to Merge
1. The Loop
- Update main
- Branch off
- Commit
- Push
- Open PR
- Review
- Fix
- Merge
- Delete branch
2. Start and Publish
bash
git switch main && git pull --ff-only && git switch -c feat/login-form
git push -u origin feat/login-form
git push-u sets upstream once; later plain git push works
- Open the PR from the pushed branch: link in push output, or
gh pr create --fill - Mark Draft while work is not ready for review
3. Review and Clean Up
- Fix feedback with new commits on the same branch
- Pushing updates the PR automatically
- Remote branch: GitHub button or auto-delete setting
bash
git switch main && git pull && git branch -d feat/login-form
after merge
Remember
Never commit straight to main: every change goes through a branch and a PR.
Keeping a Branch Up to Date
1. Fetch First
git fetch originshows what changed upstream- Never touches your branch or files
- Then pick: merge or rebase
origin/main
2. Merge or Rebase
| Merge | Rebase | |
|---|---|---|
| Command | git merge origin/main | git rebase origin/main |
| History | merge commit, as it happened | linear, commits replayed |
| Hashes | same | rewritten |
| Shared branch | safe | risky |
3. Conflicts & GitHub
- Edit filesfix markers
- git addmark resolved
- --continuemerge or rebase
- --abortbail out
- GitHub Update branch merges base into your branch
- Quick catch-up: use the button
- Team wants linear history: rebase locally
4. Interview Point
- Merge or rebase? Merge keeps history, safe when shared; rebase is linear but rewrites hashes
- Why --force-with-lease? It refuses to overwrite commits you have not seen
- Conflict mid-rebase? Fix,
git add,git rebase --continue, or--abort
Opening and Reviewing a Pull Request
1. Opening a Good PR
- Title: what changed, short and specific
- Description: what, why, how tested
Closes #123auto-closes the issue on merge- Self-review the diff on GitHub before requesting reviewers
- Remove debug code and unrelated changes
markdown
## What ## Why ## How tested Closes #123
description skeleton
2. Reviewing
| Outcome | Effect |
|---|---|
| Comment | No verdict |
| Approve | Good to merge |
| Request changes | Blocks merge if protection requires reviews |
- Review the code, not the person
- Ask questions instead of commanding
- Prefix minor items with
nit: - Explain why for every blocker
3. Author Manners and Speed
- Respond to every comment
- Resolve a thread only after fixing or agreeing
- No force-push mid-review without saying so
- Review within one working day
- Small PRs get reviewed faster
Remember
Resolve only after a fix or agreement; announce any force-push.
GitHub Merge Options and Branch Protection
1. Three Merge Options
| Option | Lands on main | Log |
|---|---|---|
| Merge commit | all branch commits + a merge commit | full history, noisiest |
| Squash and merge | one commit per PR | clean, but per-commit detail lost; branch commits no longer match main |
| Rebase and merge | each commit replayed, new hashes | linear, no merge commit |
2. Branch Protection on main
- Require a pull request before merging
- Set the required approvals count
- Require status checks to pass
- Require branches up to date with main
- Block force pushes and deletions
- CODEOWNERS review: owned paths need the owning team's approval
- Enable dismiss stale approvals on new pushes
text
/payments/ @acme/payments-team /docs/ @acme/docs-team
.github/CODEOWNERS: path, then owning team
3. Common Mistakes
- Admins bypass protection: apply the rules to admins too
- Reusing a squash-merged branch brings old commits back as duplicates
After a squash merge
Delete the branch. Start the next PR from a fresh branch off main, or it hits duplicate-commit conflicts.
Branches and PRs Cheat Sheet
1. Branch, Sync, Publish
- fetch first, then
mergeorrebaseonto origin/main - After a rebase push with --force-with-lease
bash
git switch -c feat/login-form git branch -vv # list + upstream git branch -d feat/login-form # merged git fetch origin git rebase origin/main # or: git merge git push --force-with-lease # if rebased
bash
git push -u origin feat/login-form gh pr create --fill gh pr checkout 123 # review locally
2. Merge Choice
| Option | Result |
|---|---|
| Merge commit | full history |
| Squash | one clean commit per PR |
| Rebase | linear, all commits |
3. Protection on main
- Require a pull request
- Required approvals
- Required status checks
- Branch up to date
- No force push
- CODEOWNERS review
4. Top Mistakes
- Huge PRs
- Rebasing shared branches
- Plain
--force - Committing straight to main
- Reusing a squash-merged branch
Check yourself
You rebased a pushed branch onto main and plain git push is rejected. What do you run, and why not --force?
git push --force-with-lease- The rebase rewrote hashes, so your branch diverged from the remote
- The lease fails if a teammate pushed meanwhile;
--forcewould overwrite their work
You squash-merged feat/a, kept committing on it, then opened a second PR. What goes wrong?
- Squash put one new commit on main; the branch's original commits are not in main's history
- The second PR replays them, causing duplicate-commit conflicts
- Branch off fresh main for each PR
A PR had one approval. You push a fix and the merge is blocked again. Which setting caused it?
- Dismiss stale approvals on new pushes
- The old approval is cleared, so a fresh review is needed
A reviewer chose Comment, not Request changes, but left a serious concern. Is the merge blocked?
- No: Comment gives no verdict
- Only Request changes blocks, and only when protection requires reviews
- Blocking concerns need Request changes, with a reason