Skip to main content

What is the difference between git fetch and git pull?

git fetch downloads remote changes without modifying your local branches. git pull does the same download, then immediately merges into your current branch.

Theory

TL;DR

  • fetch = download only (your working branch is untouched)
  • pull = download + merge (one command, no review step)
  • Analogy: fetch is checking your mailbox; pull is checking it and opening every letter right away
  • Use fetch when you want to inspect changes first. Use pull when you trust the remote.

Quick example

bash
# FETCH: downloads, leaves your branch untouched git fetch origin # origin/main now has remote commits # Your local main: unchanged # PULL: downloads AND merges automatically git pull origin main # Equivalent to: git fetch origin && git merge origin/main # Your local main: updated with remote changes

After git fetch, your local main stays exactly where you left it. The new commits land in origin/main and wait there until you decide what to do with them.

Key difference

git fetch is a read-only operation. It updates your remote-tracking branches (origin/main) but does not touch your working directory or local branches. git pull runs fetch and then immediately runs git merge, which can create conflicts or leave your branch in a messy state. Fetch gives you a chance to look before you leap. Pull skips that step.

When to use

  • Use fetch when: reviewing changes before merging, working on a shared branch, checking what the team pushed, or not sure if conflicts exist
  • Use pull when: quick sync on a personal feature branch, working solo, or after CI passes on a trusted branch
  • Use git pull --rebase when: you want linear history without merge commits on your feature branch

Comparison table

Aspectfetchpullpull --rebase
Downloads changesYesYesYes
Modifies local branchNoYes (merge)Yes (rebase)
Creates merge commitNoYesNo
Risk of conflictsLowMediumMedium
Lets you review firstYesNoNo
When to useBefore merging important changesQuick updates on trusted branchesKeeping history linear

Common mistakes

Mistake 1: Pulling on a shared branch without checking first

bash
# WRONG: blind pull on main git pull origin main # If someone pushed breaking changes, your branch breaks immediately # RIGHT: fetch, inspect, then merge git fetch origin git log origin/main -3 git diff main origin/main git merge origin/main

Mistake 2: Thinking fetch updates your local branch

bash
# WRONG assumption git fetch origin git log main # Shows YOUR commits only - remote changes not here # RIGHT: fetch updates origin/main, not main git fetch origin git log origin/main # Remote commits are here git merge origin/main # Now combine them

Mistake 3: Pulling with uncommitted changes

bash
# WRONG: pulling with unsaved work git pull origin main # Error: Your local changes would be overwritten by merge # RIGHT: commit or stash first git stash git pull origin main git stash pop

Mistake 4: Creating messy history with repeated pulls on a feature branch

bash
# WRONG: every pull adds a merge commit git pull origin main # merge commit git pull origin main # another merge commit # History: F1 -> M1 -> F2 -> M2 -> F3 (hard to read in a PR) # RIGHT: rebase keeps history linear git pull --rebase origin main # History: F1 -> F2 -> F3 (clean, easy to review)

Real-world usage

Most teams I have worked with default to fetch on shared branches. The extra 30 seconds of review has saved hours of debugging a broken merge more than once.

  • Feature branches: fetch before merging main into your branch to spot conflicts early
  • Deployment branches: pull after CI passes; fetch on feature branches to review first
  • Monorepo: fetch to check if other teams' changes affect your workspace before integrating
  • GitHub pull requests: reviewers see remote changes without merging until approval, which is fetch behavior by design

Follow-up questions

Q: What happens if you pull and there is a merge conflict?


A: Git pauses the merge, marks conflicted files, and leaves your branch in a "merging" state. You resolve conflicts manually, then run git add and git commit to complete the merge.

Q: Why use pull at all if fetch is safer?


A: Pull is faster for low-risk situations. On a personal branch after CI passes, the review step adds overhead with no real benefit. Most teams fetch on shared branches and pull on personal ones.

Q: What does git pull --rebase do differently from git pull?


A: Instead of creating a merge commit, rebase replays your local commits on top of the remote branch. History stays linear. Use it on feature branches, but never rebase commits already pushed to shared branches because it rewrites history.

Q: If I fetch but never merge, what happens to those remote changes?


A: They stay in origin/main indefinitely. Your local branch is untouched. Check them anytime with git log origin/main or git diff main origin/main.

Q: How do you check if your branch is behind the remote?


A: After git fetch, run git log --oneline main..origin/main. Empty output means you are up to date. Any commits listed are the ones you are missing.

Examples

Safe fetch workflow before merging

Your team pushed updates to main and you need to bring them into your feature branch without surprises.

bash
# Step 1: fetch to see what changed git fetch origin # Step 2: review commit messages git log origin/main --oneline -5 # a1b2c3d Fix: handle null values in parser # d4e5f6g Feat: add caching layer # Step 3: check the actual code diff git diff main origin/main # Step 4: merge when confident git merge origin/main

This takes about 30 extra seconds. A broken merge can take much longer to untangle.

Handling a diverged branch

You committed locally while the remote also got new commits. This is a diverged state.

bash
# Remote: A -> B -> C # Your local: A -> B -> D (you committed D locally) # Option 1: git pull creates a merge commit git pull origin main # Result: A -> B -> C # \ / # merge commit # Both C and D are combined # Option 2: git pull --rebase for linear history git pull --rebase origin main # Result: A -> B -> C -> D # Your D is replayed on top of C # Cleaner for code review, but your commit hash changes

Many teams default to the rebase option on feature branches because the PR history is easier to read and review.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?