skip to content

What is the difference between git fetch and git pull?

level: juniorimportance: must knowfreq 88%

answer

  1. One command transfers, the other also integrates
  2. Think about which refs each one moves
  3. Remote-tracking refs versus your own branch
  4. Only one of them can conflict
  5. fetch is always safe; pull merges or rebases

basics

~20 s

git fetch downloads new objects and updates remote-tracking refs such as origin/main, leaving your branch and working tree untouched. git pull runs that same fetch and then immediately integrates the result into your current branch by merging or rebasing.

solid answer

~40 s

`git fetch` is the read-only half: it contacts the remote, downloads any commits, trees and blobs you are missing, and moves the remote-tracking refs under `refs/remotes/origin/*` to match what the remote now has. Your own branch pointer, your index and your working tree are not touched, so a fetch can never conflict and never loses work. `git pull` is a convenience command that runs exactly that fetch and then runs a second command — `git merge` by default, or `git rebase` when configured — to integrate the fetched tip into the branch you are on. So pull is the one that can create a merge commit, stop with conflicts, or rewrite your local commits. The practical habit is: fetch to look, then decide how to integrate.

go deeper

for a junior

Be ready to state the one-line difference and name what fetch updates: remote-tracking refs like origin/main, not your branch or your files. Knowing that pull equals fetch plus an integration step is the expected answer.

for a middle

Explain the mechanics: which ref namespace each command writes, why fetch is always safe, and the three ways the integration half of pull can end — fast-forward, merge or rebase, or refusal.

for a senior

Show the working habit: fetch, inspect the incoming commits against the remote-tracking ref, then integrate deliberately. Be able to trace a messy shared history back to blind pulls.

for a principal

Own the team-level position: whether pull is configured, restricted or discouraged, what the repository's history should look like, and how that choice interacts with review and release practice.

## The two halves of "getting other people's work" Getting changes from a remote is really two independent steps: **transfer** and **integration**. `git fetch` does only the transfer. `git pull` does the transfer and then immediately does the integration for you. Almost every confusing thing about `git pull` follows from the fact that its second half is a separate command running on your behalf. ## What git fetch actually changes When you run `git fetch origin`, Git connects to the remote, negotiates which objects you are missing, and downloads them into your object database. It then updates your **remote-tracking refs** — local, read-only bookmarks that record where the remote's branches were at the moment you last fetched. They live under `refs/remotes/origin/` and you name them `origin/main`, `origin/feature-x`, and so on. Which refs get updated is decided by the remote's fetch refspec, by default `+refs/heads/*:refs/remotes/origin/*`. What fetch does **not** touch: your current branch (`refs/heads/...`), `HEAD`, the index, and the files in your working tree. Because of that, a fetch can never produce a merge conflict, can never fail because you have uncommitted edits, and can never lose local work. It is safe to run at any time, including in the middle of your own messy work. The only thing that grows is your object database. After fetching, nothing about your checkout has changed — but `origin/main` now points at the real remote tip, so you can inspect the incoming work: `git log --oneline HEAD..origin/main` lists commits they have that you do not, and `git diff HEAD...origin/main` shows what those commits change. ## What git pull adds `git pull` runs `git fetch` with the same arguments and then, depending on configuration, runs either `git merge` or `git rebase` to reconcile your branch with the fetched tip. Three outcomes are possible: - **Fast-forward.** If you have no local commits of your own, your branch pointer simply slides forward to the fetched commit and the working tree is updated. This is what most people picture when they say "pull". - **Merge or rebase.** If you and the remote have both added commits, the histories have diverged. A merging pull creates a merge commit joining the two lines; a rebasing pull replays your local commits on top of the fetched tip, producing new commits with new hashes. - **Conflict or refusal.** The integration step can stop mid-way with conflict markers in your files, or refuse to start at all — a rebasing pull will not run with a dirty working tree, and modern Git aborts a diverging pull entirely if you have not told it whether to merge or rebase. Because pull mutates your branch and your files, it is the command that can leave you in a half-finished state. Fetch never can. ## Why interviewers care The distinction explains a whole family of everyday problems: the surprise merge commits that appear in a shared branch's history, the "why did pull just try to rewrite my commits" confusion, and conflicts arriving at an inconvenient moment. It also explains the standard safe workflow: fetch first, look at what arrived with `git log` or `git diff`, then choose the integration deliberately — `git merge --ff-only origin/main` when you just want to catch up, an explicit merge or rebase when you have diverged. ## Practical notes `git fetch --all` updates every configured remote. `git fetch` with no arguments fetches the remote configured for the current branch, falling back to `origin`. If you never fetch, your `origin/main` is stale — it reflects the last fetch, not the remote's current state, which is why `git status` can cheerfully report "up to date" while the remote is fifty commits ahead. Teams that dislike accidental merge commits usually configure the integration half explicitly rather than banning `git pull` outright.

  • After a fetch, how do you see what would land before integrating it?
    Compare against the remote-tracking ref. `git log --oneline HEAD..origin/main` lists the commits the remote has that you do not; `git diff HEAD...origin/main` shows the combined change those commits make relative to the merge base. Only after that do you run `git merge` or `git rebase` — or `git merge --ff-only origin/main` if you expect to simply catch up.
  • Can git fetch ever lose local work or leave the repository in a conflicted state?
    No. Fetch only writes new objects and moves remote-tracking refs under `refs/remotes/`; it never touches `HEAD`, your branch, the index or the working tree, so there is nothing to conflict with. The worst it does is grow the object database. Every risky behaviour people attribute to fetching actually belongs to the merge or rebase that `git pull` runs afterwards.
  • Why can git status say the branch is up to date when the remote has moved on?
    `git status` compares your branch with its remote-tracking ref, which is a local snapshot from your last fetch — not a live query of the server. Until you run `git fetch`, `origin/main` still points where it did before, so Git reports agreement with stale information. Fetch first, then read the ahead/behind counts.

saying these in an interview costs you the question

  • Says fetch downloads changes into the working tree
  • Thinks pull is just a faster fetch
  • Believes fetch can cause merge conflicts
  • Assumes origin/main is queried live from the server
  • Cannot say pull equals fetch plus merge or rebase

context