GitUpstream Branches

Upstream Branches

“Upstream” is Git’s name for the remote branch that a local branch is paired with. When you git pull, Git asks the upstream what’s new. When you git push, Git knows where to send your commits. The upstream is the small piece of config that makes git pull and git push work with no arguments.

What an upstream is
  • A reference to a branch on a remote — typically origin/<branch>.

  • Stored in .git/config as branch.<name>.remote + branch.<name>.merge.

  • Used by git status, git pull, and git push (with default push.default=simple).

Inside .git/config

Text
[branch "main"]
    remote = origin
    merge = refs/heads/main
Setting an upstream

Three common ways

Bash
# 1. On first push
git push -u origin feature-x

# 2. With branch --set-upstream-to (-u)
git branch -u origin/feature-x feature-x

# 3. When creating a branch with track
git switch -c feature-x --track origin/feature-x
Inspecting the upstream

Bash
# Show ahead/behind for current branch
git status

# All branches with their upstreams
git branch -vv

# Just the upstream of the current branch
git rev-parse --abbrev-ref --symbolic-full-name '@{u}'
# origin/main
Unsetting an upstream

Bash
git branch --unset-upstream

# Or by name
git branch --unset-upstream feature-x
Two different “upstreams”
Easy to confuse
The word **upstream** is used two ways:
1. **Branch upstream** — the remote-tracking branch a local branch is paired with (covered on this page).
2. **Repository upstream** — a remote named `upstream`, usually the canonical project when you’re working from a fork. Naming convention only — not the same thing.
@{u} — the upstream shorthand

Shorthand reference to the upstream

Bash
# Diff your branch against its upstream
git diff @{u}

# What commits do I have that the upstream doesn't?
git log @{u}..

# What commits does the upstream have that I don't?
git log ..@{u}

# Both lists side by side
git log --left-right --oneline @{u}...HEAD
Push.default options that depend on upstream
  • simple (default) — push the current branch to its upstream, but only if the names match. Refuses otherwise. Recommended.

  • upstream — push to whatever the upstream is, regardless of name match.

  • current — push to a remote branch of the same name; ignore upstream for routing.

  • matching — pushes every local branch with a matching remote branch (dangerous).

Common errors with upstream

No upstream set

Bash
git push
# fatal: The current branch feature-x has no upstream branch.
# To push the current branch and set the remote as upstream, use:
#     git push --set-upstream origin feature-x

# Fix:
git push -u origin feature-x

Tracking a renamed remote branch

Bash
# Remote branch was renamed feature-x → feature-x-v2
git fetch
git branch -u origin/feature-x-v2
Working with multiple remotes

Different upstreams for different reasons

Bash
# Pull from upstream, push to origin (common for forks)
git config branch.main.remote upstream
git config branch.main.merge refs/heads/main
git config branch.main.pushRemote origin

# Now 'git pull' goes to upstream, 'git push' goes to origin
Tip
Whenever you see “ahead N, behind M” in your status, that is the upstream working — Git is comparing your local branch against its remote-tracking pair. Without an upstream, those numbers cannot be calculated.