Lesson 11 of 30
Local commits don't review themselves. The real workflow: branch, commit, push with -u, open a PR, get reviewed, pick a merge strategy.
18 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A pull request isn't a Git feature — Git itself has no idea what a "PR" is. It's a GitHub (or GitLab/Bitbucket) concept layered on top of two Git primitives you already know: a branch, and pushing that branch to a remote. A PR is really just "here's a branch with commits on it, and a conversation attached, asking someone to merge it into another branch."
The end-to-end flow has five steps: create a branch, commit your work on it, push the branch to the remote (setting upstream tracking the first time), open a PR on that pushed branch, and merge it once it's approved. Everything GitHub adds — the diff view, the comment threads, the CI checks, the merge button — is UI wrapped around commits that already exist in your local repo before you ever open a browser.
Start a feature branch off main and commit some work:
$ git switch -c fix/debounce-timer-leak
Switched to a new branch 'fix/debounce-timer-leak'
$ vim lib/debounce.ts
$ git add lib/debounce.ts
$ git commit -m "fix: clear timer on unmount to stop the leak"
[fix/debounce-timer-leak 7c2a91f] fix: clear timer on unmount to stop the leak
1 file changed, 3 insertions(+), 1 deletion(-)
Push it. The first push from a new branch needs -u (--set-upstream) so your local branch knows which remote branch to track:
$ git push -u origin fix/debounce-timer-leak
Enumerating objects: 7, done.
...
remote: Create a pull request for 'fix/debounce-timer-leak' on GitHub by visiting:
remote: https://github.com/adeshukla/praxis/pull/new/fix/debounce-timer-leak
To github.com:adeshukla/praxis.git
* [new branch] fix/debounce-timer-leak -> fix/debounce-timer-leak
Branch 'fix/debounce-timer-leak' set up to track remote branch 'fix/debounce-timer-leak' from 'origin'.
That -u matters beyond the first push: it means every future git push and git pull on this branch can be typed bare, with no remote/branch arguments, because Git already knows where this branch lives upstream.
Now open the PR — either click the link GitHub printed, or use the CLI:
$ gh pr create --title "fix: clear debounce timer on unmount" --base main \
--body "The debounce timer wasn't cleared when the component unmounted, \
so a stale callback could still fire and touch unmounted state. \
Added a cleanup that calls clearTimeout in the effect's return function.
## Test plan
- Added a test that unmounts mid-debounce and asserts the callback never fires
- Manually verified in the timer-heavy search box"
A good PR description does three things a diff alone can't: says why the change exists (not just what changed — the diff already shows that), calls out anything a reviewer should look at specifically, and states how it was tested. "Fixed a bug" as a title and empty body is the single most common way to get a slow, low-quality review — the reviewer has to reverse-engineer intent from the diff before they can even start evaluating it.
Once someone approves, merging on GitHub gives you three real choices, and they matter:
main branches where you want an honest record of how work landed.main. Best when a branch has messy "wip", "fix typo", "actually fix it" commits and you want main's history to read as one clean unit per PR.main individually, no merge commit at all, keeping a linear history. Best when the branch already has clean, meaningful individual commits worth preserving as-is.feature/x has two new commits, but they only exist on your machine — nothing has been pushed yet.
-u on the first push isn't fatal, but it's annoying. Without it, git push on a brand-new branch errors with "no upstream branch" and hands you the exact git push --set-upstream origin <branch> command to fix it — recognize that message instead of panicking.git log on your local feature branch still shows the original unsquashed commits — delete the local branch and pull main fresh rather than trying to reconcile the two histories.gh pr create --draft) opens it without notifying reviewers or blocking on required checks the same way — useful for getting early CI feedback or sharing work-in-progress without asking anyone to review it yet.This lesson is really the branching-fundamentals concept meeting the real world: a pull request is nothing more than a pushed branch plus a review conversation platformed on top of it. Everything about how to structure that branch and its commits — one focused change, a clean message — comes straight from the commits-and-history concept; a PR just adds a human reviewer and a merge-strategy decision at the end.