How to set upstream branch in Git

Upstream tracking branches establish relationships between local and remote branches, enabling simplified push and pull commands without specifying remote and branch names. As the creator of CoreUI, a widely used open-source UI library, I’ve streamlined Git workflows for development teams throughout my 25 years of development experience. The most convenient approach is using git push -u during first push or git branch –set-upstream-to for existing branches. This method provides automatic remote tracking, eliminates repetitive command arguments, and enables status checking showing ahead/behind commit counts relative to remote.

Set upstream during push with -u flag, configure upstream for existing branch with –set-upstream-to, verify tracking configuration.

# Create new branch
git checkout -b feature-branch

# Make some commits
git add .
git commit -m 'Add new feature'

# Push and set upstream in one command
git push -u origin feature-branch

# Output shows:
# Branch 'feature-branch' set up to track remote branch 'feature-branch' from 'origin'.
# To github.com:user/repo.git
#  * [new branch]      feature-branch -> feature-branch

# Future pushes and pulls now simplified
git push   # Instead of: git push origin feature-branch
git pull   # Instead of: git pull origin feature-branch

Set upstream for existing branch:

# Check current branch tracking status
git branch -vv

# Output shows:
#   main           abc1234 [origin/main] Latest work
#   feature-branch def5678 No upstream configured

# Set upstream for current branch
git branch --set-upstream-to=origin/feature-branch

# Or shorter syntax
git branch -u origin/feature-branch

# Verify tracking was set
git branch -vv

# Output now shows:
#   feature-branch def5678 [origin/feature-branch] Feature work

Set upstream when remote branch has different name:

# Local branch: new-feature
# Remote branch: feature-new-implementation

git checkout new-feature

# Set upstream to differently named remote branch
git branch --set-upstream-to=origin/feature-new-implementation

# Now git push and git pull use the configured upstream
git push
git pull

Set upstream for all branches at once:

# Push all branches and set upstream tracking
git push --all -u origin

# This sets upstream for every local branch that exists on remote

Change upstream to different remote:

# View current remotes
git remote -v

# Add new remote
git remote add upstream [email protected]:original/repo.git

# Set current branch to track upstream instead of origin
git branch -u upstream/main

# Or during push
git push -u upstream main

Unset upstream tracking:

# Remove upstream tracking from current branch
git branch --unset-upstream

# Verify tracking was removed
git branch -vv

# Output shows no tracking info in brackets

Check upstream configuration:

# View tracking branch for current branch
git rev-parse --abbrev-ref --symbolic-full-name @{u}

# Output: origin/feature-branch

# View all branches with tracking info
git branch -vv

# Output shows:
#   main           abc1234 [origin/main] Latest commit
#   feature-1      def5678 [origin/feature-1: ahead 2] Feature work
#   feature-2      ghi9012 [origin/feature-2: behind 1] Other feature

# Check if upstream is set for current branch
git rev-parse --abbrev-ref --symbolic-full-name @{upstream} 2>/dev/null || echo 'No upstream set'

Practical workflows with upstream:

# Start new feature
git checkout -b feature/user-auth

# Work on feature
git add .
git commit -m 'Implement user authentication'

# Push and set upstream
git push -u origin feature/user-auth

# Later, just use simple commands
git push
git pull

# Check status relative to upstream
git status

# Output shows:
# On branch feature/user-auth
# Your branch is ahead of 'origin/feature/user-auth' by 2 commits.
#   (use "git push" to publish your local commits)

Fix common upstream issues:

# Issue: Pushed but forgot -u flag
git push origin feature-branch

# Fix: Set upstream after the fact
git branch -u origin/feature-branch

# Issue: Upstream branch was deleted on remote
git fetch --prune
git branch -vv

# Output shows: [origin/feature-branch: gone]

# Fix: Either delete local branch or set new upstream
git branch --unset-upstream
git branch -u origin/main

# Issue: Want to track fork's remote instead of origin
git remote add fork [email protected]:user/repo.git
git fetch fork
git branch -u fork/main

Automation with Git configuration:

# Configure Git to automatically set upstream on push
git config --global push.autoSetupRemote true

# Now git push automatically sets upstream without -u flag
git checkout -b new-feature
git push  # Automatically sets upstream to origin/new-feature

# Configure default push behavior
git config --global push.default simple

# Verify configuration
git config --get push.autoSetupRemote
git config --get push.default

Using aliases for upstream operations:

# Create helpful aliases
git config --global alias.upstream 'rev-parse --abbrev-ref --symbolic-full-name @{u}'

git config --global alias.set-upstream '!f() { git branch -u "${1:-origin/$(git branch --show-current)}"; }; f'

git config --global alias.push-new '!git push -u origin $(git branch --show-current)'

# Usage
git upstream         # Shows current upstream branch
git set-upstream     # Sets upstream to origin/current-branch-name
git push-new         # Pushes current branch and sets upstream

Here the -u flag (short for –set-upstream-to) configures tracking relationship during push operation. The tracking configuration stores remote and branch name in .git/config file. The git branch -vv displays tracking branches with ahead/behind counts in brackets. The @{u} or @{upstream} references configured upstream branch in commands. The push.autoSetupRemote config automatically sets upstream without explicit -u flag. The git status shows relationship to upstream including ahead/behind commits. The –unset-upstream removes tracking configuration when no longer needed.

Best Practice Note:

This is the upstream branch workflow we use in CoreUI development to streamline Git operations across our team. Always set upstream when pushing new branches to enable simplified future operations, use descriptive branch names that match between local and remote for clarity, configure push.autoSetupRemote globally to avoid forgetting -u flag, and regularly run git fetch –prune to keep upstream references current and remove tracking for deleted remote branches.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author