GitTracking Branches

Tracking Branches

A tracking branch is a local branch that has a known relationship to a branch on a remote. Tracking lets Git figure out automatically which remote branch to fetch from, push to, and compare with — so git pull and git push can be typed with no arguments. It is one of those “invisible until it breaks” pieces of Git that makes everyday work smooth.

Tracking vs remote-tracking branches
  • Remote-tracking branch (e.g., origin/main) — a local pointer that records where the remote branch was at the last fetch. Read-only — you never commit to it.

  • Tracking branch (e.g., your local main tracking origin/main) — a local branch with an upstream relationship to a remote branch. Editable as normal; Git knows where to push and pull.

How tracking gets set up automatically
  • git clone <url> — every local branch automatically tracks the corresponding remote branch.

  • git switch feature-x when origin/feature-x exists — creates a local feature-x tracking the remote.

  • git push -u origin feature-x — sets feature-x to track origin/feature-x going forward.

Setting tracking explicitly

Bash
# When creating a branch
git switch -c feature-x --track origin/feature-x

# Set tracking on an existing local branch
git branch --set-upstream-to=origin/main main

# Short flag
git branch -u origin/main
Inspecting tracking info

Bash
# Each branch with its upstream and ahead/behind state
git branch -vv
# * main           1f9ab2c [origin/main] Add login form
#   feature-x      d4b1e0c [origin/feature-x: ahead 1, behind 2] WIP

# Or just the current branch
git status
# On branch main
# Your branch is up to date with 'origin/main'.
Reading the brackets
  • [origin/main] — tracks origin/main, in sync.

  • [origin/main: ahead 2] — local has 2 commits the remote does not.

  • [origin/main: behind 3] — remote has 3 commits the local does not.

  • [origin/main: ahead 2, behind 3] — diverged.

  • [gone] — the tracked remote branch was deleted; safe to clean up locally.

Disconnecting a tracking branch

Bash
git branch --unset-upstream

# Or by branch name
git branch --unset-upstream feature-x
The push.default setting

Tracking interacts with push.default, which decides what git push (no arguments) actually pushes:

  • simple (default since Git 2.0) — pushes only the current branch to its upstream, AND only if the names match. Safest.

  • current — pushes the current branch to a branch of the same name on the remote, regardless of upstream.

  • upstream (formerly tracking) — pushes to the upstream.

  • matching — pushes EVERY local branch that has a matching remote branch. Dangerous; rarely used.

  • nothing — refuses to push without explicit args.

Bash
git config --global push.default current
Why tracking matters
  • Without tracking, git pull and git push need explicit remote and branch arguments.

  • git status cannot tell you “ahead 2, behind 3” without an upstream.

  • git fetch updates remote-tracking refs but git pull needs the upstream to know what to merge.

Common errors

The classic

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 it with:
git push -u origin feature-x
Reset tracking after a rename

If the remote branch was renamed

Bash
git fetch
git branch --unset-upstream
git branch -u origin/new-name
Tracking is per-branch and persistent
Tracking lives in `.git/config` (`branch.<name>.remote` and `branch.<name>.merge`). It survives across sessions and machines (if you reuse the config), but does not transfer through a normal `git clone`.
Tip
Set git config --global push.autoSetupRemote true once. Now git push on a new branch automatically sets tracking — you stop seeing the “no upstream” error forever.