Ad – 728×90
🌐 Remote Repositories

git push, pull & fetch – Syncing with Remote Repositories

Three commands handle all communication between your local repository and remotes: git fetch downloads changes safely without touching your working tree, git pull downloads and integrates them, and git push uploads your commits. Understanding the difference — especially between fetch and pull — gives you precise control over when and how your repo stays in sync.

⏱️ 20 min read 🎯 Beginner 📅 Updated 2026

git fetch – Safe Download

git fetch downloads commits, branches, and tags from the remote but does not modify your working directory or current branch. It updates only the remote-tracking branches (e.g., origin/main). This makes it completely safe — you can always fetch without risk.

Shell
# Fetch ALL branches from all remotes
git fetch

# Fetch from a specific remote
git fetch origin

# Fetch a specific branch
git fetch origin feature/login

# After fetching, see what changed
git log main..origin/main --oneline
# Shows commits on origin/main that you haven't merged yet

# Check what branches were updated
git remote show origin
Fetch first, then decide

Many experienced developers prefer git fetch over git pull because it separates two concerns: downloading remote changes (always safe) and integrating them (requires a decision). After fetching, you can review what changed with git log or git diff before deciding whether to merge or rebase.

git pull – Fetch + Integrate

git pull is shorthand for git fetch followed by either git merge or git rebase. It downloads remote changes AND immediately integrates them into your current branch.

Shell
# Pull from the tracked remote branch (most common usage)
git pull

# Pull from a specific remote and branch
git pull origin main

# Pull with rebase instead of merge (cleaner history — no merge commits)
git pull --rebase
git pull --rebase origin main

# Set rebase as the default pull strategy (recommended by many teams)
git config --global pull.rebase true
CommandWhat it doesCreates merge commit?
git pull fetch + merge Yes (if branches have diverged)
git pull --rebase fetch + rebase No — linear history
git fetch + manual merge/rebase Download, then you decide You control it

git push – Upload Your Commits

git push uploads your local commits to the remote repository, making them available to others.

Shell
# Push current branch to the tracked remote branch
git push

# Push a specific branch to origin
git push origin feature/login

# Push with -u flag (--set-upstream): sets tracking relationship
# After this, plain "git push" works for this branch
git push -u origin feature/login

# Push all local branches to origin
git push origin --all

# Push tags
git push origin --tags
ℹ️
The -u flag (--set-upstream)

The first time you push a new branch, use git push -u origin branch-name. This creates the branch on the remote AND sets up tracking so future git push and git pull commands on this branch work without specifying the remote and branch name each time. After the initial -u push, plain git push is sufficient.

Ad – 336×280

Tracking (Upstream) Branches

A tracking branch is the connection between a local branch and its corresponding remote branch. Once set, Git knows where to push and pull without you specifying the remote and branch name every time.

Shell
# See tracking info for all local branches
git branch -vv
# * main           a1b2c3d [origin/main] Fix navbar
#   feature/login  9f8e7d6 [origin/feature/login: ahead 2] Add form

# "ahead 2" means 2 local commits not yet pushed
# "behind 3" would mean 3 remote commits not yet pulled

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

# Check full remote tracking status
git status
# On branch main
# Your branch is ahead of 'origin/main' by 1 commit.

Force Push – When and How (Safely)

Normally, Git refuses to push if the remote has commits your local branch doesn't (a "non-fast-forward" push). This protects against accidentally overwriting others' work. Force push overrides this protection.

Shell
# SAFE force push: checks that no new commits appeared on remote since your last fetch
git push --force-with-lease origin feature/login

# DANGEROUS: overwrites remote blindly — can destroy teammates' work
# git push --force origin main   ← NEVER do this on shared branches
⚠️
Never force push to main/master or any shared branch

git push --force on a shared branch overwrites the remote's history. Anyone who has already pulled those commits now has a diverged history that's very hard to reconcile. Force pushing is only appropriate on your own feature branches after rebasing (and only when you're certain no one else is working on that branch). Always prefer --force-with-lease over --force — it at least checks that the remote hasn't changed since your last fetch.

Recommended Sync Workflow

Shell
# Morning routine: start by fetching latest changes
git fetch origin

# See what's new on main
git log main..origin/main --oneline

# Update your local main
git switch main
git merge origin/main        # or: git pull

# Update your feature branch with latest main
git switch feature/my-work
git rebase main              # or: git merge main

# Work, commit, then push
git push origin feature/my-work   # first push: git push -u origin feature/my-work

📋 Summary

  • git fetch — downloads remote changes to tracking branches ONLY. Safe — doesn't touch your working tree.
  • git pull — fetch + merge (or fetch + rebase with --rebase). Integrates remote changes into your current branch.
  • git push origin <branch> — upload your commits to the remote. Use -u on first push to set tracking.
  • git pull --rebase — preferred by many teams for cleaner history (no merge commits on pull).
  • git push --force-with-lease — safe force push (only after rebasing your own feature branch).
  • Never git push --force on main or any shared branch — it overwrites teammates' work.

FAQ

What's the difference between git fetch and git pull? +

git fetch downloads remote changes but doesn't touch your working tree or current branch — it only updates remote-tracking branches like origin/main. git pull fetches AND immediately merges (or rebases) those changes into your current branch. Fetch is safe and non-destructive; pull immediately changes your branch. The best practice for careful developers is to fetch, review the changes, then manually merge or rebase.

git push says "rejected" — what do I do? +

A rejection usually means the remote has commits your local branch doesn't have. Git refuses to push because it would overwrite the remote's history. Solution: first git pull (or git fetch + git rebase) to bring in the remote changes, resolve any conflicts, then git push again. The rejection is Git protecting you — it's a feature, not a bug.

Should I use git pull or git pull --rebase? +

Many experienced developers prefer git pull --rebase because it avoids creating "noise" merge commits like "Merge branch 'main' into feature/x". This keeps the history linear and easier to read. You can set it as default with git config --global pull.rebase true. However, if you're new to Git or working on a team that expects merge commits, stick with the default. Both produce the same end result — just different history shapes.

What does "Your branch is ahead of 'origin/main' by 3 commits" mean? +

It means your local branch has 3 commits that haven't been pushed to the remote yet. The fix is git push. If you see "behind N commits", run git pull. If you see both "ahead X and behind Y", you and the remote have diverged — run git pull (or git pull --rebase) to reconcile, then push.