Both git fetch and git pull talk to a remote repository, but they do very different things to your current branch. Mixing them up is one of the most common causes of unexpected merge commits and “how did my branch end up like this” moments.
git fetch downloads commits, branches, and tags from a remote and stores them under remote-tracking references like origin/main or origin/feature-x. It does not touch your working directory, your current branch, or the index.
bashgit fetch origin
After this runs, origin/main moves to the latest remote commit. Your local main branch stays exactly where it was. Fetching is read-only from your branch’s perspective — safe to run at any time with no side effects on your work.
Once fetched, you can inspect what changed before integrating anything:
bashgit log HEAD..origin/main --oneline
This shows commits that exist on the remote but not in your current branch — a preview with no consequences.
git pull is a convenience command that runs git fetch followed by an integration step. The default integration is a merge:
bashgit pull origin main# roughly equivalent to:git fetch origingit merge origin/main
After git pull, your current branch has moved forward and your working directory may contain new files, updated files, or merge conflicts. The change is immediate. git pull ALWAYS updates the branch you currently have checked out — it is worth confirming where you are before you run it.
| git fetch | git pull | |
|---|---|---|
| Downloads remote commits | Yes | Yes |
| Updates remote-tracking branches | Yes | Yes |
| Updates your current local branch | No | Yes |
| Modifies working directory | No | Yes |
| Can create merge conflicts | No | Yes |
| Safe to run at any time | Yes | Only when ready to integrate |
Use git fetch when:
Use git pull when:
main branch where you have no local commitsA bare git pull on a branch where you have local commits can create a merge commit, introduce conflicts, or trigger a rebase — all in one step. A safer pattern is to separate the steps:
bashgit fetch origingit log HEAD..origin/main --oneline # review what is coming ingit merge origin/main # integrate when you are ready
If you already ran git pull and want to undo it, ORIG_HEAD points to the commit your branch was on before the pull:
bashgit reset --hard ORIG_HEAD
<strong>⚠️ Warning:</strong> <code>git reset --hard</code> discards uncommitted changes. Use it only when you are sure you do not need the current state of your working tree.
Key flags:
git fetch --prune — removes remote-tracking branches that no longer exist on the remotegit fetch --all — fetches from every configured remote, not just origingit pull --ff-only — updates the branch only if Git can fast-forward; fails otherwise so you decide what to do next; recommended on shared branches to prevent unexpected merge commitsgit pull --rebase — replays your local commits on top of fetched changes instead of creating a merge commit; produces a linear historygit config --global pull.rebase true — makes --rebase the default behavior for all future pulls--ff-only is particularly useful on shared branches. If the pull cannot fast-forward, it fails clean and you stay in control.
Use git fetch for visibility, inspect with git log HEAD..origin/main, then merge or rebase on your own terms. When the integration is predictable, git pull --ff-only is a safer alternative to a bare pull. Leave a comment below if you run into any issues.
Sometimes the change you need already exists, just on the wrong branch. A hotfix lands…
Email is still one of the most important communication channels inside modern applications. Password resets,…
Nginx is a high-performance web server and reverse proxy trusted by some of the largest…
ufw (Uncomplicated Firewall) sits on top of iptables (or nftables on newer systems) and replaces…
When you share a server with a team or investigate unexpected activity, the first question…
The file command inspects the actual contents of a file and reports its type — regardless of…