GitForking Repositories

Forking Repositories

A fork is a personal, server-side copy of someone else’s repository, living under your own GitHub (or GitLab) account. Forking is how you contribute to projects where you don’t have push access: you fork the project, push your changes to your fork, and then open a Pull Request asking the original maintainers to pull your work back into theirs.

Fork vs clone vs branch

These three operations get confused constantly. Here’s the cheat sheet:

Operation

Where it lives

Who can push to it

Typical use

Fork

Server-side copy under YOUR account

You

Contributing to projects you don’t own

Clone

Full copy on your local machine

You locally

Working on any repo you have access to

Branch

A pointer inside one repo

Anyone with push access

Isolating a feature within a repo

Why forks exist
  • You want to contribute to an open-source project but you’re not a maintainer.

  • You want to experiment with a project without affecting the original.

  • You want to maintain a long-running custom variant (a soft fork).

  • You want a personal sandbox version of a public repo to play with.

The standard fork workflow

Almost every open-source contribution follows the same five steps. Memorise this loop — it’s the entire game.

Fork-based contribution flow

Text
  upstream (original)        origin (your fork)        local (your laptop)
  ┌──────────────────┐       ┌──────────────────┐       ┌──────────────────┐
  │ acme-co/widget   │ ◄──── │ you/widget       │ ◄──── │ widget/          │
  └────────▲─────────┘       └────────▲─────────┘       └────────┬─────────┘
           │                          │                          │
           │   5. open Pull Request   │   3. git push origin     │  1. clone
           └──────────────────────────┴──────────────────────────┘  2. branch + commit
                                                                    4. push to origin
Step 1 — Fork on GitHub

Click the Fork button at the top-right of any repo. GitHub creates github.com/your-username/repo-name instantly. You can rename it and pick which branches to copy.

Step 2 — Clone your fork

Clone YOUR fork, not the original

Bash
git clone git@github.com:your-username/widget.git
cd widget

# Add the original as 'upstream' so you can pull updates from it
git remote add upstream git@github.com:acme-co/widget.git

# Verify
git remote -v
# origin    git@github.com:your-username/widget.git (fetch)
# origin    git@github.com:your-username/widget.git (push)
# upstream  git@github.com:acme-co/widget.git       (fetch)
# upstream  git@github.com:acme-co/widget.git       (push)
Step 3 — Branch, commit, push

Normal feature-branch workflow

Bash
git switch -c fix-typo-in-readme
# ... edit files ...
git commit -am "Fix typo in README"
git push -u origin fix-typo-in-readme
Step 4 — Open a Pull Request

After pushing, GitHub shows a yellow banner with a Compare & pull request button. The PR’s base is the upstream repo’s default branch; the compare is your fork’s feature branch. See the dedicated Creating a Pull Request page for the full walkthrough.

Syncing your fork with upstream

Your fork doesn’t auto-update. While you work, the original repo keeps moving. Pull those changes in before starting new branches so you don’t branch off stale code.

Three-step upstream sync

Bash
# 1. Grab the latest commits from the original repo
git fetch upstream

# 2. Move your local main to match upstream/main
git switch main
git merge upstream/main          # or: git rebase upstream/main

# 3. Push the updated main back to your fork
git push origin main
Tip
GitHub also has a Fetch upstream button on your fork’s homepage. Click it to sync `main` without leaving the browser — Git work for non-Git people.
Keeping a feature branch in sync

Rebase your branch onto fresh upstream/main

Bash
git fetch upstream
git switch my-feature
git rebase upstream/main
git push --force-with-lease origin my-feature
Warning
Force-pushing a rebased branch is normal on *your own fork’s feature branch* — nobody else should be pushing to it. Never force-push to `upstream/main` or any shared branch.
Deleting a fork
  • Go to your fork’s Settings → General.

  • Scroll to the Danger Zone at the bottom.

  • Click Delete this repository and type the repo name to confirm.

  • Open PRs from the fork are automatically closed when the fork is deleted.

Limitations and quirks
  • One fork per user per repo. Need a second copy? Use a different account or use the duplicate trick (clone, push to a new repo).

  • Forks of private repos stay private and inherit the parent’s access rules.

  • Issues and wikis don’t fork by default — only the code and branches.

  • Forks share storage with the parent on GitHub, so they’re cheap and instant even for huge repos.

  • You can’t fork a repo you already own — GitHub won’t let you fork acme-co/widget if you ARE acme-co.

  • Detached forks — GitHub can sever the parent link via support if you really need an independent project.

Common errors
  • "This branch is N commits behind upstream/main" — run a sync; it’s harmless but signals you should rebase before opening a PR.

  • "Push rejected, non-fast-forward" on your fork — usually means you rebased; use --force-with-lease.

  • Maintainer can’t push to your PR branch — re-open the PR with "Allow edits by maintainers" ticked.

Forks are a GitHub feature, not a Git feature
Pure Git has no concept of a fork. As far as Git is concerned, `upstream` and `origin` are just two remotes pointing at two URLs. The forking *workflow* is what GitHub, GitLab, and Bitbucket built on top of that primitive to make open-source contribution practical at scale.
Tip
Right after forking, add `upstream` immediately and run `git fetch upstream` once. Future-you, three weeks deep in a long-running branch, will thank present-you for the muscle memory.