Handbooks / Git / Chapter 2

Branches & Pull Requests for Teams

7 pages · ~5 min✓ Reviewed

Builds on Git Basics: Commit, Branch, Push. Next up: Resolving Merge Conflicts.

GitPage 1

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

  1. maindeployable
  2. Branch offfeat/...
  3. Commitsall work here
  4. PRreview + CI
  5. mainmerged
  • main stays deployable: never commit straight to it
  • The PR is the gate back into main

3. Naming and Size

PatternExample
feat/short-topicfeat/login-form
fix/short-topicfix/null-cart
chore/short-topicchore/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.

GitPage 2

Core Workflow: Branch to Merge

1. The Loop

  1. Update main
  2. Branch off
  3. Commit
  4. Push
  5. Open PR
  6. Review
  7. Fix
  8. Merge
  9. 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.

GitPage 3

Keeping a Branch Up to Date

1. Fetch First

  • git fetch origin shows what changed upstream
  • Never touches your branch or files
  • Then pick: merge or rebase origin/main

2. Merge or Rebase

MergeRebase
Commandgit merge origin/maingit rebase origin/main
Historymerge commit, as it happenedlinear, commits replayed
Hashessamerewritten
Shared branchsaferisky

3. Conflicts & GitHub

  1. Edit filesfix markers
  2. git addmark resolved
  3. --continuemerge or rebase
  4. --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
GitPage 4

Opening and Reviewing a Pull Request

1. Opening a Good PR

  • Title: what changed, short and specific
  • Description: what, why, how tested
  • Closes #123 auto-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

OutcomeEffect
CommentNo verdict
ApproveGood to merge
Request changesBlocks 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.

GitPage 5

GitHub Merge Options and Branch Protection

1. Three Merge Options

OptionLands on mainLog
Merge commitall branch commits + a merge commitfull history, noisiest
Squash and mergeone commit per PRclean, but per-commit detail lost; branch commits no longer match main
Rebase and mergeeach commit replayed, new hasheslinear, 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.

GitPage 6

Branches and PRs Cheat Sheet

1. Branch, Sync, Publish

  • fetch first, then merge or rebase onto 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

OptionResult
Merge commitfull history
Squashone clean commit per PR
Rebaselinear, 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
GitPage 7

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; --force would 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