67 67. Pull Requests and Code Review
On a team, nobody should merge their own work into main without anyone else looking at it. A pull request is GitHub’s way of asking “please review my branch and merge it”. This page covers the standard team workflow, code review, linking issues, and protecting main from mistakes.
67.1 What is a pull request?
A pull request (often called a PR) is a request, on GitHub, to merge one branch into another, usually a feature branch into main. Each pull request gets its own web page with:
- a title and a description of the change,
- the list of commits and the diff of every changed file,
- comments and reviews from teammates,
- the results of any automated checks (for example, tests).
The name comes from asking the project to “pull” your changes in. (GitLab calls the same thing a merge request.) Pull requests also work across forks: you push a branch to your fork and open a pull request to the original repository (see Sharing a Repository).
67.2 The GitHub Flow
Most teams follow a simple routine called the GitHub Flow:
1. Branch git switch -c add-projects-page
2. Commit git add ... and git commit ... (as often as you like)
3. Push git push -u origin add-projects-page
4. Open a PR on github.com, or with gh pr create
5. Review teammates comment, approve, or request changes;
new commits pushed to the branch update the PR
6. Merge on github.com, or with gh pr merge
7. Clean up delete the branch; git switch main; git pull
main only ever receives reviewed work, and every change has a page that explains why it was made.
67.3 Steps 1-3: Branch, commit, and push
Next on the team’s list is a projects page (issue #1), and Sam takes the job. He starts from an up-to-date main, creates a branch, and commits his work there (“Add projects page”, “Link to projects page from home page”), exactly as on Branches and Merging. At this point, the newest commit on main is Maria’s 9c2c605 (“Change heading to Our Portfolio”); you’ll see that ID again in the outputs below.
git switch main
git pull
git switch -c add-projects-pageThen he pushes the branch to GitHub:
git push -u origin add-projects-pageOutput (progress lines omitted):
To https://github.com/maria-lopez/git-tutorial-project.git
* [new branch] add-projects-page -> add-projects-page
branch 'add-projects-page' set up to track 'origin/add-projects-page'.
67.4 Step 4: Open the pull request
On github.com: open the repository. Right after a push, a yellow banner offers Compare & pull request; click it. Check the two branch menus: base is where the changes should go (main) and compare is your branch (add-projects-page). Write a title and a description, then click Create pull request. If the work isn’t finished yet but you want early feedback, open the menu next to that button and choose a draft pull request instead.
From the terminal: the GitHub CLI (gh, which you may have installed for signing in on Putting Your Repository on GitHub) can do the same:
gh pr create --title "Add projects page" --body "Adds src/projects.html and links it from the home page. Fixes #1"gh prints the web address of the new pull request. Useful options:
| Option | What it does |
|---|---|
--fill |
Use your commit messages for the title and description |
--draft |
Open it as a draft |
--base main |
Choose the branch to merge into (the default is the repository’s default branch) |
--reviewer USERNAME |
Ask a teammate to review it |
--web |
Finish creating it in your browser |
Keep pull requests small (one feature or fix), and say what changed, why, and how to test it. Fixes #1 links the pull request to issue number 1 (see Issues below).
67.5 Step 5: Review
Code review means a teammate reads the changes before they are merged. On the pull request page:
- Open the Files changed tab to see the diff.
- To comment on a line, hover over it and click the blue comment icon, type your comment, and click Start a review.
- Click Review changes, write a summary, and choose one option: Comment (general feedback), Approve (ready to merge), or Request changes (must be fixed before merging). Then click Submit review.
To fix what a reviewer asked for, the author doesn’t open a new pull request. He just commits on the same branch and pushes again, and the pull request updates itself:
git pushOutput (progress lines omitted):
To https://github.com/maria-lopez/git-tutorial-project.git
c3d6678..d38fddc add-projects-page -> add-projects-page
Reviewers can also work from the terminal: gh pr checkout 2 downloads pull request 2’s branch so they can run and test it, and gh pr review 2 --approve or gh pr review 2 --request-changes --body "Please fix the link" submits a review.
What to look for in a review:
- Does it work and do what the description says? Run it.
- Is it readable, small, and focused?
- Any bugs, missing cases, or leftover debugging code?
- Any secrets, such as API keys or passwords?
Review AI-written code just as carefully: it often looks polished even when it is wrong.
67.6 Steps 6-7: Merge and clean up
When the pull request is approved, someone with write access clicks Merge pull request and then Confirm merge at the bottom of the pull request page, then clicks Delete branch, since the branch is no longer needed. (gh pr merge 2 --merge --delete-branch does the same from the terminal.)
GitHub did the merge, so everyone’s computer is now behind. Sam updates his main and deletes his local copy of the branch:
git switch main
git pullOutput (progress lines omitted):
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
From https://github.com/maria-lopez/git-tutorial-project
9c2c605..8cf4abd main -> origin/main
Updating 9c2c605..8cf4abd
Fast-forward
src/index.html | 1 +
src/projects.html | 14 ++++++++++++++
2 files changed, 15 insertions(+)
create mode 100644 src/projects.html
(Before the pull, Git still thinks main is up to date: it only learns about the merge on GitHub when it fetches.)
git branch -d add-projects-page
git fetch --pruneOutput:
Deleted branch add-projects-page (was d38fddc).
From https://github.com/maria-lopez/git-tutorial-project
- [deleted] (none) -> origin/add-projects-page
git branch -d deletes his local branch; git fetch --prune removes his local record (origin/add-projects-page) of the branch that was deleted on GitHub. The history now shows the merge commit that GitHub created, named after the pull request:
git log --oneline --graphOutput (older commits cut off):
* 8cf4abd (HEAD -> main, origin/main, origin/HEAD) Merge pull request #2 from maria-lopez/add-projects-page
|\
| * d38fddc Clarify project name
| * c3d6678 Link to projects page from home page
| * 33260fe Add projects page
|/
* 9c2c605 Change heading to Our Portfolio
The merge button has a menu with up to three methods (repository owners can turn some off):
| Method | What lands on main |
|---|---|
| Create a merge commit | All of the branch’s commits, plus a merge commit (what Sam’s PR used) |
| Squash and merge | One single new commit containing all of the branch’s changes |
| Rebase and merge | The branch’s commits, replayed one by one on top of main, without a merge commit |
Squashing keeps main’s history short (one commit per pull request); merge commits keep every step. One surprise after a squash merge: your local branch’s original commits are not on main, so git branch -d may refuse to delete the branch (“not fully merged”). Once you’ve confirmed on GitHub that the pull request was merged, git branch -D branch-name is safe.
67.7 Issues and linking pull requests
GitHub issues are the project’s to-do and bug list. Each issue gets a number (#1, #2, …; pull requests share the same numbering). You can create one on the Issues tab or with gh issue create --title "Add a projects page".
Writing #1 in a pull request or comment links to issue 1. Writing a closing keyword such as Fixes #1, Closes #1, or Resolves #1 in the pull request’s description closes issue 1 automatically when the pull request is merged into the repository’s default branch (usually main).
67.8 Protecting main
As of Oct 16, 2026 · Official docs: About rulesets · Available rules for rulesets
Nothing in Git stops someone, or an AI agent, from pushing straight to main, force-pushing over it, or deleting it. GitHub can: a ruleset is a list of rules for some of the repository’s branches. (The older way to do the same, branch protection rules, still works.) A typical ruleset for main:
- Restrict deletions: nobody can delete
main. - Block force pushes: nobody can overwrite
main’s history. - Require a pull request before merging: every change reaches
mainthrough a pull request; a directgit pushtomainis rejected. You set how many approvals a pull request needs. On a team, 1 or more. In a solo project, 0: GitHub never lets you approve your own pull request, so with 1 required approval you could never merge. - Require status checks to pass before merging: once the project has automated tests that run on GitHub, a pull request can’t be merged until they pass.
To create one: on the repository’s page, click Settings, then Rules → Rulesets in the left sidebar, then New ruleset → New branch ruleset. Give it a name, set Enforcement status to Active (new rulesets start as Disabled, which enforces nothing), click Add target → Include default branch under Target branches, tick the rules, and click Create. The Bypass list lets chosen people (for example the repository’s admins) ignore the rules; leave it empty if the rules should apply to you too.
For example, the course’s demo repository yr-2026-full-stack-demo has a ruleset named protect-main with the first three rules and 0 required approvals. Every change, including the ones Claude Code makes, has to go through a pull request, and a mistaken git push --force can’t destroy main. That’s a cheap safety net against your own mistakes and your AI agent’s.
Rulesets (and branch protection rules) work in public repositories on the free plan. In private repositories, GitHub enforces them only on paid plans (GitHub Pro, Team or Enterprise Cloud). Students can get GitHub Pro free through GitHub Education.
67.9 AI in the pull request workflow
Claude Code can open pull requests for you and review code, both in your session and on GitHub. See AI in the Pull Request Workflow.
67.10 Key takeaways
- A pull request asks to merge a branch and gives the team a page to discuss, review, and check the change first.
- GitHub Flow: branch → commit → push → pull request → review → merge → delete the branch → pull
main. - Open PRs on github.com (Compare & pull request) or with
gh pr create; review on the Files changed tab with Comment, Approve, or Request changes. - More commits pushed to the branch update the pull request.
Fixes #1closes issue 1 when the PR is merged into the default branch. - A ruleset can protect
main: block force pushes and deletions, and require a pull request (and passing checks) for every change, including your AI agent’s.
Practice Questions
Easy
Question 1 · Short answer
What is a pull request, and why do teams use them instead of merging directly into main?
Question 2 · Ordering
Put the steps of the GitHub Flow in order:
- A. Open a pull request
- B. Merge the pull request
- C. Create a branch
- D. Push the branch to GitHub
- E. Teammates review the changes
- F. Commit your changes
- G. Delete the branch and pull
main
Question 3 · Matching
Match each review option with its meaning.
| Option | Meaning | |
|---|---|---|
| 1. Comment | A. The changes must be fixed before the pull request is merged | |
| 2. Approve | B. General feedback, without approving | |
| 3. Request changes | C. The changes are ready to merge |
Question 4 · True or false
After a reviewer requests changes, the author must close the pull request and open a new one with the fixes.
Question 5 · Short answer
In a pull request, what are the base branch and the compare branch?
Question 6 · Multiple choice
Which text in a pull request’s description closes issue 7 automatically when the pull request is merged into the default branch?
See issue 7#7 pleaseFixes #7Issue: seven
Medium
Question 7 · Write the command
You finished your work on the branch fix-footer and committed it. Write the command that publishes the branch to GitHub for the first time, and the gh command that opens a pull request with the title “Fix footer year”.
Question 8 · Scenario
Your pull request was merged on GitHub and its branch was deleted there. On your laptop, git status on main still says Your branch is up to date with 'origin/main'. Is your main really up to date? What should you run?
Question 9 · Multiple choice
A teammate opened pull request 14 and you want to run the code on your computer before approving it. Which command gets you the branch?
gh pr create 14gh pr checkout 14git clone 14gh pr merge 14
Question 10 · Short answer
List four things a reviewer should check in a pull request.
Question 11 · Compare
What is the difference between “Create a merge commit” and “Squash and merge” on GitHub’s merge button?
Question 12 · Read the output
After pulling, Sam sees:
* 8cf4abd (HEAD -> main, origin/main, origin/HEAD) Merge pull request #2 from maria-lopez/add-projects-page
|\
| * d38fddc Clarify project name
| * c3d6678 Link to projects page from home page
| * 33260fe Add projects page
|/
* 9c2c605 Change heading to Our Portfolio
Which merge method was used, how many commits were on the pull request’s branch, and who created the merge commit?
Hard
Question 13 · Scenario
Maria’s pull request was squash-merged. Back on her laptop she runs git switch main, git pull, and git branch -d add-about-page, and Git refuses, saying the branch is not fully merged. Is her work lost? What should she do?
Question 14 · Long answer
Your team requires a pull request for every change to main. Give three advantages and one cost of this rule.
Question 15 · Scenario
A teammate merged their own pull request into main one minute after opening it, without any review, and the site broke. Suggest two changes to the team’s process or repository settings to prevent this.
Question 16 · Write the command
Pull request 5 has been approved. Write one gh command that squash-merges it and deletes its branch, then the Git commands you run on your laptop afterwards.
Question 17 · Scenario
Maria works alone on her public portfolio repository. She creates a ruleset for main with Require a pull request before merging and sets the required approvals to 1. Now she can’t merge any of her pull requests. Why, and what should she change? What does the ruleset still protect her from after the change?
Question 18 · Short answer
Sam creates a ruleset for main with the right rules, but a direct git push to main still works. Name two settings he should check.