Fetching Changes (git fetch)
git fetch downloads new commits, branches, and tags from a remote — but does not touch your local branches. Everything new is stored under origin/<branch> references. You then choose what to do with it: merge, rebase, inspect, or ignore. Fetch is the safe, read-only “show me what’s new” operation.
The basic invocation
git fetch # fetch from the default remote (origin) git fetch origin # fetch from origin explicitly git fetch --all # fetch from every remote configured
What fetch does
Connects to the remote.
Downloads all new commits, branches, and tags.
Updates remote-tracking pointers (e.g.,
origin/main).Leaves your local branches completely untouched.
What fetch does NOT do
Does not modify your working directory.
Does not modify your local branches.
Does not produce conflicts (it never merges).
Cannot lose work — it is read-only locally.
After fetching: inspect the changes
What did the remote learn?
git fetch # What commits did origin/main get since I last fetched? git log HEAD..origin/main --oneline # Just show me how many git rev-list --count HEAD..origin/main # Visual graph git log --graph --oneline --all -20
Integrating fetched changes
After inspecting, decide how to integrate
# Option A: fast-forward / merge into the current branch git merge origin/main # Option B: rebase your local commits on top git rebase origin/main # Option C: just look — do nothing else
git pull does the fetch + integrate in one step. Many developers prefer the two-step approach (fetch, then explicitly merge or rebase) because it gives them a chance to inspect first.
Useful flags
--all— fetch from every configured remote.--prune(or-p) — also remove local pointers for branches deleted on the remote.--tags— also fetch tags. Tags are not fetched by default in some configurations.--depth=N— fetch only the last N commits of each branch (shallow fetch).--unshallow— turn a shallow clone into a full clone.--dry-run— show what would be fetched without doing it.--no-tags— skip tags.<remote> <branch>— fetch only one branch.
Fetching one specific branch
git fetch origin feature-x # Downloads only feature-x's new commits. # After this, you can: git switch feature-x # auto-creates local branch tracking origin/feature-x
Pruning stale branches
Remove local pointers to branches deleted on the remote
git fetch --prune # - [deleted] (none) -> origin/old-branch # Make it the default git config --global fetch.prune true
Inspecting all remote branches at once
git fetch --all git branch -r # origin/HEAD -> origin/main # origin/main # origin/develop # origin/feature-x # See log of every remote branch git log --all --oneline --graph -20
Fetch vs pull — when to choose which
fetch — “show me what’s on the remote.” You decide what to do next. Recommended default.
pull — “show me what’s on the remote AND merge it into my current branch.” Saves a step but commits you to an immediate merge.
The cautious dance
git fetch git status # check whether your branch is behind, ahead, or in sync git log HEAD..origin/$(git branch --show-current) --oneline # what's new? # Decide: merge, rebase, or ignore
Common errors
“fatal: could not read from remote repository” — wrong URL, network issue, or auth problem.
“refusing to fetch into current branch” — almost never happens with default config; check
git config receive.denyCurrentBranch.Tags or branches piling up — use
--pruneregularly.
git fetch before git status if you want the “ahead / behind” counts to reflect today’s remote — Git only knows what it has seen on the last fetch.