Fork vs Clone
These two terms are often confused because they sound similar but serve different purposes:
| Fork | Clone | |
|---|---|---|
| What | Creates YOUR copy of the repo on GitHub's servers | Downloads a repo (or fork) to your local machine |
| Where | GitHub web interface (one click) | Your terminal (git clone <url>) |
| Why | So you have a place to push changes without write access to the original | So you can work on the code locally |
| Result | A new repo at github.com/YOUR-USERNAME/repo-name |
A local copy in a folder on your computer |
If you have write access to the repository (e.g., it's your own repo, or a team repo where you're a collaborator), you don't need to fork — clone directly and push branches. Forking is specifically for contributing to repos where you don't have write access.
The Complete Open-Source Contribution Workflow
Here's the full workflow from zero to merged PR:
Step 1: Fork the repository on GitHub
Go to the repo on GitHub and click the Fork button (top-right). GitHub creates a copy at github.com/YOUR-USERNAME/repo-name. This is now yours to push to.
Step 2: Clone YOUR fork to your local machine
# Clone YOUR fork (not the original)
git clone https://github.com/YOUR-USERNAME/repo-name.git
cd repo-name
# "origin" now points to YOUR fork
git remote -v
# origin https://github.com/YOUR-USERNAME/repo-name.git (fetch)
# origin https://github.com/YOUR-USERNAME/repo-name.git (push)
Step 3: Add the original repo as "upstream"
git remote add upstream https://github.com/ORIGINAL-AUTHOR/repo-name.git
git remote -v
# origin https://github.com/YOUR-USERNAME/repo-name.git (fetch)
# origin https://github.com/YOUR-USERNAME/repo-name.git (push)
# upstream https://github.com/ORIGINAL-AUTHOR/repo-name.git (fetch)
# upstream https://github.com/ORIGINAL-AUTHOR/repo-name.git (push)
Step 4: Create a feature branch
# Always branch off main (or the default branch)
git switch main
git switch -c fix/typo-in-readme
Step 5: Make your changes and commit
# Edit files, then stage and commit
git add README.md
git commit -m "fix: correct spelling of 'repository' in README"
Step 6: Push your branch to YOUR fork
git push -u origin fix/typo-in-readme
# Counting objects: 3, done.
# Branch 'fix/typo-in-readme' set up to track remote branch 'fix/typo-in-readme' from 'origin'.
Step 7: Open a Pull Request on GitHub
Go to GitHub. You'll see a yellow banner: "Your recently pushed branch: fix/typo-in-readme — Compare & pull request". Click it.
- Base repository: ORIGINAL-AUTHOR/repo-name, branch: main
- Head repository: YOUR-USERNAME/repo-name, branch: fix/typo-in-readme
Writing a Good PR Description
A clear PR description helps reviewers understand your change quickly:
## What does this PR do?
Fixes a typo in README.md: "repositry" → "repository".
## Why?
Incorrect spelling in the getting-started section.
## How to test?
1. Open README.md
2. Search for "repository" — should be spelled correctly throughout.
## Checklist
- [x] Typo fixed
- [x] No other changes in this PR
Handling Code Review
Reviewers may leave comments requesting changes. You don't need to close and reopen the PR — just push more commits to the same branch. The PR updates automatically.
# Make the requested change
git add README.md
git commit -m "fix: also correct spelling in contributing guide per review"
git push # pushes to the same branch — PR updates automatically
# If asked to squash commits before merging, use interactive rebase:
git rebase -i main
# Squash to one clean commit, force-push your branch:
git push --force-with-lease
Keeping Your Fork in Sync with Upstream
While your PR is being reviewed, the original repo may get new commits. Keep your fork up to date:
# Fetch latest from the original repo
git fetch upstream
# Update your local main
git switch main
git merge upstream/main # fast-forward if you haven't committed to main directly
# Push the updated main to YOUR fork on GitHub
git push origin main
# Update your feature branch if needed
git switch fix/typo-in-readme
git rebase main # rebase onto updated main
GitHub also provides a "Sync fork" button on your fork's main page that updates your fork's default branch to match upstream. This is convenient but only updates the remote. You still need to run git pull locally to get those changes on your machine.
📋 Summary
- Fork = your copy of someone else's repo on GitHub (needed when you don't have write access).
- Clone = download a repo to your local machine.
- Complete workflow: Fork → Clone →
git remote add upstream→git switch -c branch→ commit →git push -u origin branch→ open PR. - A PR is opened from your fork's branch to upstream's main. GitHub shows the diff clearly.
- To respond to review: push more commits to the same branch — the PR updates automatically.
- Sync fork:
git fetch upstream+git merge upstream/mainon your local main, then push to origin.
FAQ
No — only when you don't have write access to the repository. If you're a collaborator on a team repo, you can clone directly and push branches without forking. Forking is the mechanism that allows anyone to contribute to any public repo on GitHub without needing special permissions from the repo owner.
Yes — each PR is tied to a specific branch, not the fork as a whole. You can have one branch for a bug fix and another for a new feature, each with its own open PR simultaneously. Just make sure each branch is based off the latest main and they don't modify the same files in conflicting ways.
Not necessarily. Keeping your fork is useful if you plan to contribute again. Delete the feature branch (git branch -d fix/typo-in-readme locally, and on GitHub via the PR page's "Delete branch" button). Sync your fork's main with upstream so it's ready for your next contribution. Only delete the fork entirely if you're done contributing to that project.
They're the same concept with different names. GitHub calls it a "Pull Request" (PR). GitLab calls it a "Merge Request" (MR). Bitbucket also uses "Pull Request". The workflow is identical: you're requesting that someone pull/merge your branch into their branch. The terminology difference is purely platform convention.