Week 3: GitHub Collaboration & Pull Requests

Everything so far has lived on one machine. This week connects your local repo to GitHub — a remote host that adds collaboration on top of Git: pushing and pulling history, forking someone else's project, and using pull requests as the standard way real teams review and merge each other's code.

Module 3 of 5 Week 3 of 5 ~2–3 Hours Hands-on Exercise Included

By the end of this week, you'll be able to

  • Connect a local repo to GitHub over SSH and push/pull/fetch confidently
  • Fork a repo and work through the fork-and-PR contribution workflow
  • Open a pull request, respond to review comments, and link it to an issue

1. Git vs. GitHub & Setting Up SSH

Git is the version control tool; GitHub is a company that hosts Git repositories and layers collaboration features on top — pull requests, issues, code review, CI, and more. GitLab and Bitbucket are competing hosts built on the same underlying Git; nothing about Git itself is GitHub-specific.

Authenticate with an SSH key so you're not typing a password or token on every push. Generate one, then add the public half to your GitHub account:

terminal
ssh-keygen -t ed25519 -C "ada@example.com"
# Accept the default file location; a passphrase is optional but recommended.

cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAA... ada@example.com
# Copy this entire line into GitHub -> Settings -> SSH and GPG keys -> New SSH key

ssh -T git@github.com
# Hi ada! You've successfully authenticated...

2. Remotes: clone, push, pull & fetch

A remote is a named reference to a repo hosted elsewhere — origin is the conventional name for the one you cloned from or push to by default.

terminal
# Starting from an existing GitHub repo:
git clone git@github.com:your-user/hello-git.git
cd hello-git
git remote -v
# origin  git@github.com:your-user/hello-git.git (fetch)
# origin  git@github.com:your-user/hello-git.git (push)

# Or wire up a remote to a repo you already have locally:
git remote add origin git@github.com:your-user/hello-git.git
git push -u origin main   # -u remembers this as main's default remote/branch

fetch, pull and push are the three commands that move history between local and remote:

terminal
git fetch origin          # download new commits from origin, but don't merge them
git log origin/main       # inspect what's new before touching your own branch

git pull                  # fetch AND merge (or rebase) into your current branch, in one step
git push                  # upload your local commits to the remote
Prefer fetch when you want to look before you leap

git pull is really git fetch followed by an automatic merge — convenient, but it can surprise you with a merge or a conflict mid-workflow. fetch alone lets you inspect what changed with git log origin/main before deciding how to bring it in.

3. Forking & the Fork-and-PR Workflow

A fork is your own personal copy of someone else's repository on GitHub. It's the standard way to contribute to a project you don't have write access to — you can't push directly to their repo, so you push to your fork instead, then ask them to pull your changes in via a pull request.

terminal
# 1. Click "Fork" on GitHub, then clone YOUR fork:
git clone git@github.com:your-user/some-project.git
cd some-project

# 2. Add the original repo as a second remote, conventionally named "upstream":
git remote add upstream git@github.com:original-owner/some-project.git

# 3. Branch, commit, push to YOUR fork (origin):
git switch -c fix-typo
# ... edit files ...
git commit -am "Fix typo in README"
git push -u origin fix-typo

With upstream wired up, keeping your fork current is a fetch-and-merge (or rebase) against upstream/main, exactly like syncing any other remote branch:

terminal
git fetch upstream
git switch main
git merge upstream/main
git push origin main    # keep your fork's main in sync too

4. Opening & Reviewing Pull Requests

A pull request (PR) proposes merging one branch into another and opens a dedicated space for discussion, line-by-line comments, and automated checks, before anything actually merges. On GitHub, after pushing a branch:

  1. GitHub shows a "Compare & pull request" prompt for the branch you just pushed — or open one manually from the Pull Requests tab.
  2. Pick the base branch (usually main) and the compare branch (your feature branch), write a clear title and description of what changed and why.
  3. Request reviewers. They can leave comments on specific lines, approve, or request changes.
  4. Push more commits to the same branch to update the PR automatically — no need to open a new one.
  5. Once approved (and checks pass, covered in Week 5), merge via GitHub's "Merge pull request" button — a standard merge, squash, or rebase merge, depending on the repo's convention.
Keep pull requests small

A PR that changes 40 lines gets a careful review in minutes. A PR that changes 4,000 lines gets a rubber-stamp approval nobody actually read closely. Small, focused PRs are consistently the single biggest lever for review quality on a real team.

5. Issues, Labels & Linking Commits

GitHub issues track bugs, feature requests and tasks — independent of any specific branch or commit. Reference an issue number in a commit message or PR description to link them automatically, and certain keywords auto-close the issue when the PR merges:

terminal
git commit -m "Fix null pointer on empty cart (fixes #42)"
# In a PR description, any of these auto-close issue #42 on merge:
# Closes #42 / Fixes #42 / Resolves #42

Labels (bug, enhancement, good first issue) and assignees turn a flat issue list into something a team can actually triage and plan around — most repos also use a Project board to arrange issues into a Kanban-style view.

6. Hands-on Exercise

Hands-on

Open a real pull request against your own repo

Practice the exact loop you'll use on every real project: branch, push, PR, merge.

Requirements:

  1. Create a new public GitHub repo, push a local repo to it, and confirm git remote -v shows origin.
  2. Create an issue describing a small change (e.g. "Add a Contributing section to the README").
  3. Branch off main, make the change, and commit with a message that references the issue number (e.g. "Add Contributing section (closes #1)").
  4. Push the branch and open a pull request against main from the GitHub UI.
  5. Leave at least one review comment on your own PR (GitHub allows this), then merge it.
  6. Confirm the linked issue closed automatically, and pull the merged change back into your local main.
Hint

The closing keyword (closes, fixes, resolves) only auto-closes an issue when it appears in the default branch's merge — putting it in the PR description works as well as a commit message.

7. Knowledge Check

Four quick questions. Expand each to check your answer.

Q1

What's the practical difference between git fetch and git pull?

fetch downloads new commits from the remote but leaves your current branch untouched — you can inspect them first. pull does a fetch and then immediately merges (or rebases) those commits into your current branch, which can trigger a merge or conflict you weren't expecting.

Q2

Why fork a repo instead of just cloning it and pushing directly?

You typically don't have write access to push directly to someone else's repository. A fork gives you your own copy under your account that you can push to; you then propose your changes back via a pull request, which the original repo's maintainers review and merge on their terms.

Q3

Why is a large, sprawling pull request generally worse for a team than several small ones?

Reviewers can realistically hold a small, focused diff in their head and give it genuine scrutiny. A very large diff tends to get skimmed rather than reviewed, which defeats the purpose of code review — bugs and design issues are far more likely to slip through unnoticed.

Q4

What does writing "Fixes #42" in a PR description or commit message actually do?

It links the commit or PR to issue #42, and GitHub automatically closes that issue once the change lands on the repo's default branch. It's a convenience for traceability — without a closing keyword, the link would need to be added and the issue closed manually.