Forks and Open-Source Contributions
When you have write permission in a team repository, you can create and push a feature branch there. In many open-source projects you have no permission to push to the original repository. A fork gives you your own hosted copy under your account so you can publish work and propose it back.
Fork, clone, and branch are different
Section titled “Fork, clone, and branch are different”| Action | Where it happens | Result |
|---|---|---|
| Fork | Hosting platform | A separate repository under another account, connected to the original as a fork |
| Clone | Your computer | A local Git repository copied from a hosted repository |
| Branch | Within a repository | Another movable name for a line of commits |
Forking does not create a local folder. Cloning does. A branch does not create a separate GitHub repository. GitHub fork relationships are platform metadata; ordinary Git itself does not have a git fork command.
Some private repositories forbid forking, and organization policies may restrict where a fork can be created. A fork is not a permission bypass: you can push to your copy, not automatically to the original.
Typical contribution path
Section titled “Typical contribution path”Suppose the original project is acme-learning/order-api and your account is YOU:
- Use GitHub’s Fork action to create
YOU/order-api. - Clone your fork. The new
originpoints to your repository. - Add the original project as
upstreamso you can fetch its new commits. - Create a task branch, commit, test, and push it to your fork.
- Open a PR from your fork’s task branch into the original project’s intended base branch.
git clone https://github.com/YOU/order-api.gitcd order-apigit remote add upstream https://github.com/acme-learning/order-api.gitgit remote -vExpected relationships:
Your computer├── origin → YOU/order-api (your fork: you can push)└── upstream → acme-learning/order-api (original: normally fetch)These are conventional remote names, not reserved Git keywords. A project might name them differently.
Contribute a focused change
Section titled “Contribute a focused change”Update your local base from the original before starting new work:
git fetch upstreamgit switch maingit merge --ff-only upstream/maingit switch -c fix/payment-validationMake and test the change:
git add src/PaymentService.cs tests/PaymentServiceTests.csgit commit -m "fix: reject invalid payment currency"dotnet testgit push -u origin fix/payment-validationOn GitHub, open a PR whose head is YOU:fix/payment-validation and whose base is the appropriate branch of acme-learning/order-api. The maintainers may review, request changes, or close the PR. Having a fork does not guarantee acceptance.
Keep the fork in sync
Section titled “Keep the fork in sync”The original project’s main keeps moving. Your hosted fork and local clone do not update themselves automatically. A straightforward path, if your local main has no independent commits:
git fetch upstreamgit switch maingit merge --ff-only upstream/maindotnet testgit push origin mainThe fetch updates your local knowledge of the original. The merge advances local main. The push updates your hosted fork. You may instead use GitHub’s Sync fork interface to update the hosted fork, then fetch or pull locally. Either route requires deliberate coordination between the three repositories.
If the fast-forward fails, your local main has diverged. Inspect the graph and decide how to integrate; do not immediately use a hard reset or force push. Keep original-project work and personal feature work on separate branches whenever possible.
Sometimes maintainers ask contributors to update their PR branch with the latest base. That is distinct from merely syncing your fork’s main and may involve a merge or a carefully scoped rebase.
Which workflow should you choose?
Section titled “Which workflow should you choose?”| Situation | Usual path |
|---|---|
| You have write permission in the shared repository | Create a feature branch there, push it, open a PR |
| You lack write permission to the original | Fork, clone your fork, push a branch there, open a cross-repository PR |
| You only want to read or run a public project | Clone; no fork is required |
Even collaborators may choose forks for isolation or policy reasons. The table is a common pattern, not a hard Git rule.
Common mistakes
Section titled “Common mistakes”- Saying fork and clone are the same operation.
- Assuming
originalways means the original open-source repository. - Pushing to
upstreamwhen you have no permission. - Opening a PR against your own fork when you meant to contribute to the original.
- Assuming the fork automatically follows original-project updates.
- Force-resetting a diverged fork without checking personal commits.
- Treating a public fork as private; its visibility and permissions need review.
Summary
Section titled “Summary”A fork is a separate hosted repository, a clone is a local repository, and a branch is a line of work within one repository. In a common open-source setup, origin names your fork and upstream names the original. Fetch upstream updates your local knowledge; merge or rebase updates a local branch; push origin updates your hosted fork. A PR proposes the final change to the original maintainers.
Knowledge check
Section titled “Knowledge check”- Which action creates a repository under your GitHub account?
- After cloning your fork, where does
originnormally point? - What does
git fetch upstreamchange locally, and what does it not update on GitHub? - Which branch and repository should a contribution PR target?
- Why can
git merge --ff-only upstream/mainrefuse during fork sync?