Two words that are easy to confuse. They are different operations at different levels.
Clone: a local copy
git clone git@github.com:original/repo.git
What it does: creates a local copy of the repository on your
machine. The remote repository stays unchanged. You get everything:
history, branches, tags. Writes (push) work only if you have
permissions on original/repo. Without them, git push will be
rejected.
Details in clone.
Fork: a copy on the server
You fork through the forge's UI: the "Fork" button on GitHub/GitLab/Bitbucket. What happens: GitHub creates a full copy of the repository under your account:
Before: github.com/original/repo
After: github.com/original/repo
github.com/you/repo ← your copy
This is not local. It is a server-side operation: GitHub now has two repositories, your fork and the original. You are the full owner of your fork: you can push, create branches, delete things, whatever you like. Your fork has no effect on the original.
Typical open-source flow
1. Fork (in GitHub UI): original/repo → you/repo
2. Clone your fork: git clone git@github.com:you/repo.git
3. (optional) add the original as upstream (see [[upstream-vs-origin]])
4. Make changes, push to your fork
5. Open a PR on GitHub: you:feature → original:main
This is the "fork flow." Most large open-source projects do not allow external contributors to push directly to the original; they simply do not have the permissions. A fork works around that: you have write access to your fork, you do the work there, and the original receives changes only through PRs.
When you do not need a fork
If you are a team member of the original repository with writer access, you do not need a fork. The cycle is simpler:
1. Clone the original
2. Branch inside it, push to the original
3. PR from branch to main, everything inside one repository
Small teams work exactly this way. A fork is a workaround for missing permissions, not "the proper way."
How fork and clone differ technically
| What | Clone | Fork |
|---|---|---|
| Lives | Locally, your disk | On the server, your GitHub account |
| Initiated by | git clone command | UI on the forge |
| Affects the original | No | No |
| Requires GitHub | No (works with any git URL) | Yes (forge-specific feature) |
| How many times | As many as you want | One fork per account |
| Can pull from upstream | Yes (via upstream-vs-origin) | Yes (plus Sync button on GitHub) |
One fork is one copy. If you need multiple copies, you need a different account or an organization.
Syncing a fork with upstream
Over time the original moves ahead and your fork falls behind. To sync:
Via UI: use the "Sync fork" button on your fork's page on GitHub. It performs a fast-forward when possible.
Via CLI:
git fetch upstream
git switch main
git rebase upstream/main
git push origin main
The CLI works in any setup; the UI button works only in the standard flow. More detail in upstream-vs-origin.
When fork vs clone is a real decision
- You want to modify your own project: clone, nothing else needed.
- You want to contribute to someone else's open-source project: fork, then clone your fork.
- You want to use someone else's code without modifying it: clone. A fork is an unnecessary extra step.
- You want to create your own version of a project (for example, after a disagreement with the author): fork (you can treat it as a hard fork and develop it independently).
Pitfalls
- "I forked, now I'll push to the original." No: a fork is your
copy; push to it. Changes reach the original through a PR. See
upstream-vs-origin.
- The fork goes stale. After a year without syncing it can be
many commits behind the original. Before opening a PR, always run
fetch upstream + rebase. - Fork deleted from GitHub takes all its branches and issues with it. A PR from that fork to the original also becomes invalid. Keep a backup if the fork has unmerged branches.
- The fork goes stale. After a year without syncing it can be
many commits behind the original. Before opening a PR, always run
- Private fork of a public repository. GitHub does not let you fork
a public repository into a private one directly. Use
Importvia the UI or mirror-push instead. With GPL this is legal as long as you keep modifications private: GPL imposes obligations (disclose source and preserve copyleft) only at the moment of distributing the binary or source to others; personal use is unrestricted.