Forking & Contributing to Open Source
Reviewed & published by Brayan K
Open source runs on forks and pull requests. By the end of this lesson you'll fork a project, wire up the origin and upstream remotes, keep your fork in sync, and submit your first real contribution.
Part of the free Git course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
What You'll Learn
- Fork a repository to get your own pushable copy on GitHub
- Clone your fork and understand that origin points at it
- Add the original project as the upstream remote
- Keep your fork in sync: fetch upstream, merge, push to origin
- Branch, commit, and push a focused change to your fork
- Open a pull request from your fork into the original project
1️⃣ Fork and Clone
Click Fork on the project's GitHub page to create github.com/YOU/project — your own copy you can push to. Then git clone your fork's URL. Cloning sets origin to your fork automatically.
# The open-source contribution flow starts with a FORK — your own copy of
# the project on GitHub that you're allowed to push to.
#
# 1. On the project's GitHub page, click "Fork" (top-right). GitHub creates
# github.com/YOU/project from github.com/ORIGINAL/project.
#
# 2. Clone YOUR fork to your machine (note: your username in the URL):
git clone https://github.com/YOU/project.git
cd project
# 'origin' now points at YOUR fork — confirm it:
git remote -v2️⃣ Add the upstream Remote
Your fork is frozen at the moment you forked. To track the real project, add it as a second remote called upstream. The convention is simple: push to origin (your fork), pull updates from upstream (the original).
# Your fork is a snapshot from when you forked it. To stay current with the
# real project, add it as a second remote called "upstream" (by convention).
git remote add upstream https://github.com/ORIGINAL/project.git
# Now you have two remotes:
# origin -> YOUR fork (you push here)
# upstream -> the original (you pull updates from here)
git remote -v3️⃣ Keep Your Fork in Sync
Before starting new work, pull the original's latest commits so your branch builds on current code. git fetch upstream downloads them, then you merge (or rebase) upstream/main into your main, and push so your fork matches.
# Keeping your fork in sync with the original (do this before new work):
# 1) Download the latest commits from the original project
git fetch upstream
# 2) Bring them into your local main
git switch main
git merge upstream/main # or: git rebase upstream/main
# 3) Push the freshened main up to your fork so it matches too
git push origin mainYour turn. Wire up the two remotes after cloning a fork. Fill in the two blanks.
# 🎯 YOUR TURN — replace each ___ then run it after forking a repo.
# Goal: wire up the two remotes correctly.
# 1) Clone your fork (origin is set automatically by clone)
git clone https://github.com/YOU/project.git
cd project
# 2) Add the ORIGINAL project as a remote named upstream
git remote ___ upstream https://github.com/ORIGINAL/project.git
# 👆 the subcommand that registers a new remote
# 3) Prove both remotes exist
git remote ___ # 👉 the flag that lists remotes with URLs
# ✅ Expected: you see origin (your fork) AND upstream (the original).4️⃣ Contribute via Pull Request
Now make your change on a branch, push it to your fork, and open a pull request whose base repository is the original and head is your fork's branch. Tick Allow edits by maintainers so they can polish it if needed.
Common Errors (and the fix)
- "Permission denied" pushing to the original: you cloned the original instead of your fork. Clone github.com/YOU/project, push to origin, and PR into upstream.
- Your PR shows unrelated commits: your fork is stale. Sync first — git fetch upstream then merge/rebase upstream/main before branching.
- "upstream does not appear to be a git repository": you didn't add it. Run git remote add upstream <original-url>.
- PR opened into your own fork: on the compare page, set the base repository to the original, not your fork.
- Working directly on main: always branch first — a clean main makes syncing and future PRs painless.
Pro Tips
- 💡 Read CONTRIBUTING.md first: projects state their style, tests, and PR expectations there.
- 💡 Start small: docs fixes and "good first issue" tickets are the friendliest way in.
- 💡 Sync before you branch: it prevents most merge conflicts in your PR.
- 💡 Use gh repo fork --clone: the GitHub CLI forks, clones, and adds upstream in one command.
📋 Quick Reference
| Command | Purpose |
|---|---|
| git clone <your-fork-url> | Get your fork locally (sets origin) |
| git remote add upstream <orig-url> | Track the original project |
| git fetch upstream | Download the original's latest commits |
| git merge upstream/main | Bring updates into your main |
| git push origin branch | Push your work to your fork |
| gh repo fork --clone | Fork + clone + add upstream |
Mini-Challenge: Your First Contribution
No commands given this time — just the plan. Take a small change all the way to a PR on a real project.
# 🎯 MINI-CHALLENGE: a real open-source contribution.
# No commands given — just the plan. Use a real (small, friendly) project.
#
# 1. Read the project's README and CONTRIBUTING guide first
# 2. Fork it, clone YOUR fork, and add the original as "upstream"
# 3. Sync: fetch upstream, merge upstream/main into your main
# 4. Branch, make a small focused change, commit, push to origin
# 5. Open a PR into upstream/main with a clear description; allow maintainer edits
#
# ✅ Expected: a pull request appears on the ORIGINAL repo, proposing your
# branch from your fork — your first open-source contribution.
# your commands here🎉 Lesson Complete!
- ✅ A fork is your own pushable copy of someone else's repo
- ✅ origin is your fork; upstream is the original project
- ✅ Sync with git fetch upstream + merge/rebase before new work
- ✅ Push branches to origin, then PR into upstream's main
- ✅ "Allow edits by maintainers" speeds up getting merged
Practice quiz
What is a fork on GitHub?
- A branch in the original repo
- A deleted repo
- Your own server-side copy of someone else's repository under your account
- A type of merge
Answer: Your own server-side copy of someone else's repository under your account. A fork is a full copy of another repo on GitHub, owned by you, that you can push to freely.
Why fork instead of cloning directly when contributing to open source?
- You usually can't push to a repo you don't own; a fork gives you a copy you CAN push to
- Forks are faster
- Cloning is deprecated
- Forks skip review
Answer: You usually can't push to a repo you don't own; a fork gives you a copy you CAN push to. Without write access you can't push to the original, so you push to your fork and open a PR from it.
After forking, what do you do to get the code on your machine?
- git fork
- git pull upstream
- Nothing
- git clone <your-fork-url>
Answer: git clone <your-fork-url>. You clone YOUR fork's URL to get a local working copy you can push back to.
By convention, what remote name points at the ORIGINAL project?
- origin
- upstream
- source
- base
Answer: upstream. By convention origin is your fork and upstream is the original repository you forked from.
What does 'origin' point to in a typical fork setup?
- Your fork
- The original repo
- The main branch
- Nothing
Answer: Your fork. git clone of your fork sets origin to your fork; you add upstream separately for the original.
How do you add the original project as a remote?
- git upstream add <url>
- git remote upstream <url>
- git remote add upstream <original-url>
- git fork upstream
Answer: git remote add upstream <original-url>. git remote add upstream <url> registers the original repo so you can fetch its updates.
How do you bring the latest changes from the original into your fork's main?
- git pull origin
- git fetch upstream then merge/rebase upstream/main, then push to origin
- git fork sync
- git reset upstream
Answer: git fetch upstream then merge/rebase upstream/main, then push to origin. Fetch upstream, integrate upstream/main into your main, then push to keep your fork in sync.
Where do you open a pull request when contributing from a fork?
- Into your own fork only
- Into a new repo
- You email a patch
- From your fork's branch into the upstream (original) repo
Answer: From your fork's branch into the upstream (original) repo. You push a branch to your fork and open a PR targeting the upstream repository's base branch.
What does 'Allow edits by maintainers' do on a PR from a fork?
- Deletes your fork
- Lets the project's maintainers push fixes to your PR branch
- Auto-merges the PR
- Hides the PR
Answer: Lets the project's maintainers push fixes to your PR branch. It grants maintainers push access to your PR branch so they can tweak it before merging.
What's a good first step before writing a big contribution?
- Force-push to upstream
- Delete the README
- Read the project's CONTRIBUTING guide and open/claim an issue
- Rebase upstream/main
Answer: Read the project's CONTRIBUTING guide and open/claim an issue. Checking CONTRIBUTING and discussing in an issue avoids wasted work and respects the project's norms.
Continue this course
- Previous: GitHub Pull Requests & Code Review
- Next: Intro to GitHub Actions (CI/CD) — Automate tests and deploys on every push with GitHub Actions workflows
- Quick reference: Git cheat sheet
Frequently asked questions
What's the difference between forking and cloning?
Forking happens on GitHub and creates a server-side copy of someone else's repo under your account — one you're allowed to push to. Cloning happens on your machine and downloads a repo (usually your fork) into a local folder so you can edit it. For open source you typically fork first, then clone your fork.
Why do I need a fork at all — can't I just push a branch?
Only if you have write access. Most open-source projects don't give random contributors push access to the original repo, so you can't push a branch there. A fork gives you a full copy you DO own and can push to; you then open a pull request from your fork into the original. (Maintainers and team members with write access can skip forking and push branches directly.)
What are origin and upstream?
They're remote names, by convention. After cloning your fork, origin points at your fork — that's where you push. You then add upstream pointing at the original project — that's where you fetch the latest changes from. Keeping these two straight is the heart of the fork workflow: push to origin, pull from upstream.
How do I keep my fork up to date with the original?
Fetch the original and integrate it: git fetch upstream, then on your main run git merge upstream/main (or git rebase upstream/main), then git push origin main so your fork's main matches. Do this before starting new work so your branch is built on the latest code and avoids needless conflicts. GitHub also has a 'Sync fork' button for the simple case.
Where does the pull request go when contributing from a fork?
You push your branch to your fork (origin), then open a PR whose base repository is the ORIGINAL project and base branch is usually main, with the head being your fork's branch. Ticking 'Allow edits by maintainers' lets the project's maintainers push small fixes to your branch, which often speeds up getting merged.