Skip to main content

git fetch & git pull — Getting Remote Changes

The Difference

CommandWhat it does
git fetchDownloads remote commits and updates remote-tracking refs (origin/main) — does not touch your working tree or local branches
git pullRuns git fetch and then immediately integrates those changes into your current branch (via merge or rebase)

The golden rule: Prefer git fetch + manual inspect over git pull when you want to see what's changed before integrating. Use git pull --rebase for routine updates to keep history linear.


git fetch

Fetch from origin (default remote)

git fetch
git fetch origin

Fetch a specific branch

git fetch origin main

Fetch all remotes

git fetch --all

Fetch and prune deleted remote branches

git fetch --prune
# or configure it globally:
git config --global fetch.prune true

Inspect what was fetched before integrating

# View commits that are on origin/main but not on your local main
git log main..origin/main --oneline

# See the diff
git diff main origin/main

# Then merge when ready
git merge origin/main

git pull

git pull = git fetch + git merge (by default) or git fetch + git rebase (with --rebase).

Default pull (fetch + merge)

git pull origin main

This creates a merge commit if your branch has diverged from the remote, which can clutter history.

git pull --rebase origin main

This replays your local commits on top of the fetched commits, keeping history linear without a merge commit.

Set rebase as the default pull strategy globally

git config --global pull.rebase true

Pull and automatically stash/unstash local changes

git pull --rebase --autostash
# Stashes uncommitted changes, pulls, replays commits, then pops the stash

Handling Diverged History

When your branch and the remote have both moved forward, you have three options:

Local:   A -- B -- C         (your commits)
\
Remote: A -- B -- D -- E (remote commits you don't have yet)

Option 1: Merge (creates a merge commit)

git pull origin main
# Result: A -- B -- C -- M (M = merge commit of C and E)
# \ /
# D -- E

Option 2: Rebase (linear — preferred for feature branches)

git pull --rebase origin main
# Result: A -- B -- D -- E -- C' (C replayed on top of E)

Option 3: Fast-forward only (reject if diverged)

git pull --ff-only origin main
# Fails if branches have diverged — forces you to decide explicitly

Useful Flags Summary

fetch flags

FlagMeaning
--allFetch from all remotes
--pruneRemove remote-tracking refs for deleted remote branches
--tagsFetch all tags
--depth=NShallow fetch — only last N commits
-vVerbose output

pull flags

FlagMeaning
--rebaseRebase instead of merge after fetch
--ff-onlyOnly fast-forward — abort if history diverged
--autostashStash before pull, pop after
--no-commitFetch and merge but don't auto-commit the merge
--prunePrune stale remote-tracking branches during fetch

Establish a Routine

Before starting work each day, run:

git fetch --prune
git log HEAD..origin/main --oneline # see what teammates pushed
git pull --rebase origin main # catch up

This keeps your branch current and avoids large, painful merges at PR time.