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.

Interview Questions (Senior Level)โ€‹

  1. How do you design team defaults for pull behavior to reduce history drift?
  2. When should engineers avoid git pull and prefer explicit fetch + inspect?
  3. What risks come with always-on rebase pulls in shared branches?
  4. How do you operationalize --ff-only in protected branch workflows?

Short answer guide:

  • Standardize pull strategy by branch type and governance needs.
  • Use fetch-first when risk or uncertainty is high.
  • Rebase can rewrite context and confuse shared history if misused.
  • --ff-only enforces explicit conflict resolution before integration.
Interview Focus

Compare fetch, pull --rebase, and pull --ff-only using branch policy and team collaboration context.

Interview Trap

Using git pull blindly on shared branches without understanding merge/rebase side effects.