Skip to content
Pipelines and Pizza 🍕
Go back

GitHub Forks Explained

5 min read

Snowed in today, so you get a bonus post. Sometimes being trapped at home is productive.

A fork is your own copy of someone else’s repository on GitHub. That’s it. Nothing magical.

I remember the first time I saw “Fork” on GitHub and thought it was way more complicated than it actually is. It’s not. Let me save you that confusion.

Fork vs Clone

This trips people up constantly, so let’s clear it up:

ActionWhat it doesWhere it lives
ForkCopies a repo to your GitHub accountGitHub (remote)
CloneDownloads a repo to your machineYour computer (local)

You typically do both: fork first, then clone your fork. Fork gets you a copy you own, clone gets it on your laptop so you can actually work on it.

When to Fork

Fork when:

  • You want to contribute to open source (you can’t push to their repo directly)
  • You need to customize something for your own use
  • You want to experiment without breaking the original

Don’t fork when:

  • You already have write access — just clone and branch, don’t overcomplicate it
  • You only want to read the code — clone is enough

I’ve seen people fork their own team’s repos when they already had push access. Don’t be that person. It just creates confusion.

Why Bother Forking?

It’s your playground. Break things. Push garbage commits. Nobody cares — it’s your copy. When I’m learning a new codebase, I’ll fork it just so I can add console.log statements everywhere without shame.

Customization without waiting. I’ve forked tools to add features I needed right now instead of waiting months for a maintainer to maybe merge my PR. Sometimes you just need it to work your way.

Your backup plan. Projects get abandoned. Repos get deleted. I’ve watched popular tools vanish overnight. If you’ve forked it, you’re not stranded when the original disappears.

The open source handshake. This is how contributing works. You can’t push to kubernetes/kubernetes, but you can push to your-name/kubernetes and ask them nicely to pull your changes in.

The Workflow

Here’s what it looks like in practice:

# 1. Fork on GitHub (click the Fork button — top right of the repo page)

# 2. Clone YOUR fork (not the original)
git clone git@github.com:YOUR-USERNAME/repo-name.git
cd repo-name

# 3. Add the original as "upstream" so you can pull their updates
git remote add upstream git@github.com:ORIGINAL-OWNER/repo-name.git

# 4. Verify you've got both remotes
git remote -v
# origin    git@github.com:YOUR-USERNAME/repo-name.git (fetch)
# origin    git@github.com:YOUR-USERNAME/repo-name.git (push)
# upstream  git@github.com:ORIGINAL-OWNER/repo-name.git (fetch)
# upstream  git@github.com:ORIGINAL-OWNER/repo-name.git (push)

That upstream remote is important. Without it, you can’t easily pull in updates from the original project.

Keeping Your Fork in Sync

Here’s the thing — the original repo doesn’t stop just because you forked it. They’re shipping features, fixing bugs, moving on with life. Your fork? It’s frozen in time unless you update it.

Option 1: Merge (The Safe Way)

This is what I recommend for most people:

git fetch upstream
git checkout main
git merge upstream/main
git push origin main

You’ll get a merge commit in your history. That’s fine. It’s honest — it shows exactly what happened.

Option 2: Rebase (The Clean Way)

If you’re particular about a linear history:

git fetch upstream
git checkout main
git rebase upstream/main
git push origin main --force-with-lease

Fair warning: only rebase if you’re the only one working on your fork. Rebasing rewrites history, and if someone else has pulled from your fork, you’re about to ruin their day.

So Which One?

Merge. Just use merge. Unless you have a specific reason to rebase and you understand the implications, merge is safer and works fine.

When Your Fork Goes Off the Rails

Sometimes you let your fork sit for six months and now it’s 200 commits behind with conflicts everywhere. We’ve all been there.

The Nuclear Option

If your fork is a disaster and you just want to start fresh:

git fetch upstream
git checkout main
git reset --hard upstream/main
git push origin main --force

This throws away everything on your main branch and resets to match upstream exactly. Everything. Make sure that’s what you want.

Cherry-Picking

If upstream has specific commits you want but you don’t need everything:

git fetch upstream
git log upstream/main --oneline  # find the commit you want
git cherry-pick abc1234          # grab just that commit

Surgical precision. Take only what you need.

Contributing Back

Made something useful? Here’s how you give it back:

  1. Push your changes to your fork
  2. Go to the original repo on GitHub
  3. Click “New pull request”
  4. Click “compare across forks”
  5. Select your fork and branch as the source

Write a good description, explain what you changed and why, and hit submit. Now you wait for the maintainers to review it.

Pro tip: smaller PRs get merged faster. Nobody wants to review 47 files.

The Mistake I See All The Time

Forking when you don’t need to.

If you’re on a team and you have write access to the repo, just clone it and make a branch. Forking adds a layer of complexity that serves no purpose when you already have access.

Fork = I don’t have push access, so I need my own copy.

Branch = I have push access, I’m just working on a feature.

Know the difference. Use the right tool.

Stay warm out there.

Happy automating!