Git · Lesson 5 · 35 min

Git: pull requests & code review

On almost every team, nobody pushes straight to main. You push a branch and open a pull request (PR): “here's my change, please check it and pull it in.” Teammates review it, you fix what they find, and then it's merged. This lesson walks through a whole PR, from first push to clean-up, including the two things that trip people up: review changes and an out-of-date branch.

You will learn

  • Connect to GitHub with an SSH key
  • The pull request flow: branch, push, open, review, fix, merge
  • Update a PR whose branch is out of date, safely, with --force-with-lease
  • Squash, merge or rebase: the three merge buttons
  • How to write a good PR, and how to review one kindly

Getting set up with GitHub

Make a free account at github.com, then let your computer prove who it is with an SSH key, the same kind of key as in Linux Basics, lesson 3:

Same on both
ssh-keygen -t ed25519 -C "you@example.com"   # skip if you already have ~/.ssh/id_ed25519
cat ~/.ssh/id_ed25519.pub                    # copy this into GitHub → Settings → SSH and GPG keys
ssh -T git@github.com                        # "Hi NAME! You've successfully authenticated…"

GitHub's own command-line tool, gh, does pull requests without the browser. Install it, then log in once with gh auth login:

TaskRocky / RHELUbuntu / Debian
Install ghsudo dnf install epel-release, then sudo dnf install ghsudo apt install gh
Log ingh auth login same on both

Everything gh does, you can also do on the website. The buttons have the same names.

The pull request flow

  1. Branch: git switch -c add-faq. One branch per change, with a name that says what it is.
  2. Commit and push: git push -u origin add-faq. GitHub even prints a link to open a PR.
  3. Open the PR: gh pr create --title "…" --body "…", or the green button on the website.
  4. Review: teammates read the diff and leave comments. They approve or request changes.
  5. Fix: commit and push to the same branch. The PR updates by itself. There's no need to open a new one.
  6. Merge: once it's approved (and the automatic checks pass), merge it, delete the branch, and git pull on main.

Many teams turn on branch protection for main: nobody can push to it directly, every PR needs an approving review, and the branch must be up to date with main before it can merge. The playground's club repository works that way.

“This branch is out-of-date with the base branch”

While your PR waits for review, other PRs get merged, so main moves on. To bring your branch up to date, rebase it onto the new main (as in lesson 4), then push. The plain push is refused, because rebasing rewrote your commits:

Same on both
git fetch                         # get the new main
git rebase origin/main            # replay your commits on top of it
git push --force-with-lease       # replace the branch on GitHub
--force-with-lease, never plain --force

Both replace the branch on the server. --force-with-lease first checks that nobody else pushed to it since you last fetched, and refuses if they did, so you can't wipe out a teammate's commits by accident. And this only ever goes on your PR branch. Never force-push main.

Some teams prefer git merge origin/main into the branch instead. That needs no force-push, but adds a merge commit. Both are fine, so do what your team does.

The three merge buttons

Button / gh flagWhat lands on mainGood for
Squash and merge --squashOne commit with all the PR's changes, titled “Add an FAQ page (#12)”A tidy main: one commit per PR. Very common.
Create a merge commit --mergeEvery commit from the branch, plus a merge commitKeeping the full detail of how the work was done
Rebase and merge --rebaseEvery commit from the branch, replayed onto main, no merge commitStraight history with each commit kept

After a squash, your local branch's commits aren't on main (the squash is a new commit), so delete the branch with git branch -D, or let gh pr merge --delete-branch do it.

Good PRs, kind reviews

Forks: contributing to someone else's project

You can't push branches to a project you're not a member of, so you fork it: GitHub makes your own copy, you push your branch there, and open the PR from your fork to theirs. To keep your fork's main up to date, add the original as a second remote, usually called upstream:

git clone git@github.com:YOU/project.git
git remote add upstream https://github.com/THEM/project.git
git fetch upstream && git rebase upstream/main       # catch up with the original

Try it: your first pull request 🔀

The club website lives in /srv/git/site.git, which acts like GitHub here: gh is wired to it, and main is protected. You wrote an FAQ page for new members (~/faq.html). Get it onto the website the proper way. Priya will review it.

Quick check

1. A reviewer asked for a change on your open PR. How do you send the fix?

2. You rebased your PR branch onto the new main. git push is rejected. What now?

3. What does “Squash and merge” put on main?

Finished the missions and the quiz? Mark it done to track your progress.