The Forking Workflow
Forking creates your own server-side copy of a repository you cannot push to, so you can make changes and propose them back through a pull request. It is the standard model for open source and for any contribution that crosses an organization boundary, because it requires no write trust: you work entirely in your copy until a maintainer chooses to merge.
The whole workflow comes down to keeping two remotes straight — the original repo and your copy of it — and not letting your copy drift so far behind that the eventual pull request is a wall of conflicts. Get those two habits right and forking is no harder than branching.
Fork, Origin, Upstream
When you fork, your copy becomes origin — the remote you clone from and push to. The original repository is conventionally added as a second remote named upstream, which you fetch from but never push to. Keeping these two names straight is the entire mental model: you pull new work from upstream and publish your contributions to origin.
A fresh clone of your fork has only origin configured. You add the original with git remote add upstream <url>, and from then on git remote -v shows both, making it obvious which is yours and which is the source of truth.
Syncing a Fork
Your fork is a snapshot taken at the moment you created it; it does not update itself. The instant the original repository gains a commit, your fork is behind. You catch up with git fetch upstream followed by a merge or rebase onto upstream/main, or by clicking the "Sync fork" button GitHub shows on the fork's home page.
Syncing before you start each piece of work is what keeps a pull request small and reviewable. A fork that has not been synced in weeks produces a diff against a base the maintainer no longer recognizes.
Contributing via Pull Request
You never work on your fork's default branch. You create a feature branch in your fork, push it to origin, and open a pull request whose base is the upstream repository's branch and whose head is your fork's branch. GitHub recognizes the fork relationship and offers the cross-repository PR automatically.
Branching per contribution lets you have several pull requests open at once, each isolated, and lets you keep working while one of them waits for review.
Maintainer-Side Controls
When you open the pull request, the "Allow edits by maintainers" checkbox lets a maintainer push small fixes directly to your branch — a one-line typo or a rebase — instead of asking you to do it across a timezone gap. Maintainers can also fetch your branch locally to test or amend it before merging.
Fork vs Branch Decision
The choice is governed by access. If you have push access to the repository — you are on the team — you branch directly and skip the upstream sync entirely; branch protection applies to your branch as-is. If you do not have push access — open source, an external contributor — you fork, because it gives isolation without anyone having to grant you write permission first.
Forking workflow — fork when you lack push access, as in open source or cross-org work. You get isolation by default and need no write trust, at the cost of maintaining an upstream remote and syncing your fork as the original moves.
Shared-repository (branch) workflow — branch directly when you are on the team with push access. It is simpler: no second remote, no fork syncing, and branch protection applies to your branch immediately. Choose it whenever you already have write permission.
- Committing to your fork's default branch and opening the PR from it — every later upstream sync then conflicts and you cannot run two pull requests at once.
- Letting a fork sit untouched for weeks, then opening a PR from a months-old base — the maintainer gets a conflict-heavy diff and bounces it back to you to rebase.
- Forgetting to add an
upstreamremote, so you keep fetching from your own stale fork and never see new commits on the original. - Leaving "Allow edits by maintainers" unchecked, so a maintainer who could fix a one-line nit instead has to ask you to do it across timezones.
- Force-pushing a rebase to your PR branch mid-review without warning — reviewers lose the comment anchors tied to the old commits.
- Add the original repo as
upstreamand rungit fetch upstream && git rebase upstream/mainbefore starting each piece of work. - Always branch off an up-to-date base in your fork, and never commit to the fork's default branch.
- Enable "Allow edits by maintainers" when opening a PR so a maintainer can push small fixes directly.
- Open the pull request against the correct upstream base branch, not your own fork's branch.
- Delete merged feature branches in your fork and re-sync from
upstreambefore the next contribution.
Knowledge Check
You have push access to a repository on your team. Fork or branch?
- Branch directly — with push access you skip the fork, avoid an
upstreamremote, and branch protection covers it - Fork — every contribution should go through a personal copy regardless of your access level
- Fork, because feature branches on a shared repository cannot be covered by branch protection or rulesets at all
- Neither; commit your changes straight to the default branch and skip the PR
Why does a pull request from a months-old fork often get bounced back?
- The fork's base has drifted far behind upstream, so the diff is full of conflicts the maintainer asks you to rebase
- GitHub automatically blocks pull requests from any fork created more than 30 days ago
- After enough time passes an old fork quietly loses its connection to the original repository and can no longer target it for a PR
- A fork can only ever produce one pull request before it must be recreated
What is the role of the upstream remote?
- It points at the original repository so you can fetch new work from it, while
originstays the fork you push to - It is the branch you push your changes onto before opening a pull request
- It is GitHub's built-in name for your fork's own default branch
- It is a backup remote that mirrors
originautomatically on every push so that your fork always keeps a second copy
What does "Allow edits by maintainers" enable on your pull request?
- A maintainer can push small fixes directly to your PR branch instead of asking you to make them
- It grants you full write access to the upstream repository for the entire life of the pull request, letting you push to any of its branches
- It auto-merges the pull request into the base branch as soon as the required checks pass
- It lets maintainers delete your fork automatically from your account once the PR is merged and closed
You got correct