linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Chapters
  • How it works
  • Lessons
  • Knowledge base
  • Interview prep
home/git/kb/Remote repositories/upstream-vs-origin

kb/remote ── Remote repositories ── intermediate

upstream vs origin

Two conventional remote names. `origin` is where you cloned from (usually your fork). `upstream` is the "real" project you forked. This is just a convention: nothing is magic, both names can be renamed.

view as markdownaka: origin-vs-upstream, upstream-and-origin

In open source, most work happens through a fork. The typical setup:

github.com/original-project/awesome   ← the original, you do not write here
github.com/me/awesome                  ← your fork, you write here

Locally it is convenient to configure two remotes:

bash
# After cloning your fork
git clone git@github.com:me/awesome.git
cd awesome
# Add the original as upstream
git remote add upstream git@github.com:original-project/awesome.git
git fetch upstream

Now:

  • origin is your fork. You push your branches here.
  • upstream is the original. You pull others' updates from here.

Why you need both

Without upstream you get updates only through the GitHub UI: "Sync fork" in the browser. That works, but the cycle is slow and does not fit scripts or CI.

With upstream, "sync with the original" takes two commands:

bash
git fetch upstream
git switch main
git rebase upstream/main      # or git merge upstream/main
git push origin main          # update main in your fork

No UI required. Repeatable from the terminal.

Workflow for a new PR

bash
# 1. Fetch the original
git fetch upstream
# 2. Create the feature branch from fresh upstream/main, not from origin/main
git switch -c feat/my-fix upstream/main
# 3. ... commits ...
# 4. Push to your fork (origin), not to upstream
git push -u origin feat/my-fix
# 5. On GitHub open a PR: from me:feat/my-fix → original-project:main

The key point in step 2: branch from upstream/main, not from origin/main. Otherwise your fork may be a day behind, and a bunch of stale commits will end up in the PR.

These are just names

Git knows nothing about "original" and "fork." This is a convention, nothing more. You can call them mine and theirs and everything works the same:

bash
git remote rename origin mine
git remote rename upstream theirs

But in a team it is easier to use common names so that instructions like "git fetch upstream && git rebase upstream/main" work the same for everyone.

When you do not need upstream

If you have no fork and push directly to the main repository (a team member, an owner), upstream is not needed. One origin, standard flow.

Pitfalls

  • Accidental push to upstream. If you have write access to upstream (for example, you are a maintainer of the original and your fork is for experiments), you can accidentally git push upstream main and update the original's main. Branch protection rules prevent that.
  • origin/main and upstream/main diverging. If someone else pushed to your fork separately (another contributor, a copy), main in the fork and main in upstream will drift apart. Fix: sync with git push origin upstream/main:main (or recreate the fork).
  • Forgetting to switch upstream after a forge migration (GitHub to GitLab). If the original moved, update with git remote set-url upstream <new>.

§ команды

bash
git remote add upstream <original-url>

Add the original repository as a second remote

bash
git fetch upstream

Pull in changes from the original

bash
git switch -c feat/x upstream/main

Branch from fresh upstream, not your fork

bash
git rebase upstream/main

Catch up to the original before a PR

§ см. также

  • remote-cmdgit remoteManages the list of URLs your repository is connected to. After `clone` there is one remote named `origin` by default. You can add a second one (`upstream` for fork flow), remove remotes, or rename them.
  • fetchgit fetchDownloads updates from a remote but **does not touch** your local branches. Updates only refs/remotes/origin/. A safe command: after fetch you can see what arrived and decide what to do with it.
  • fork-vs-cloneFork vs cloneClone is a local copy of a repository. Fork is a copy **on the server** under your account. In open source you usually fork first (gaining write access to your copy), then clone the fork (to work locally), and open a PR from the fork back to the original.
  • clonegit cloneCreates a local copy of a remote repository. Under the hood: `init` + add origin + `fetch` the full history + `checkout` the default branch. The first command you run on any project you did not create yourself.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies