git pull fetches commits from a remote repository and merges them into your current local branch. It’s actually two commands in one — git fetch followed by a merge (or rebase, depending on configuration) — which is exactly why modern Git insists you tell it which reconciliation strategy you want. This is the tenth post in this site’s Git command guide, following Git Push.
Basic Usage
Say your local repository is on main and you want the latest changes from the remote’s feature branch:
$ git pull origin feature
This fetches the feature branch from origin and merges it into whatever branch you currently have checked out. More commonly, you’ll just be syncing your current branch with its own remote counterpart:
$ git pull
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Total 5 (delta 2), reused 5 (delta 2), pack-reused 0
Unpacking objects: 100% (5/5), 1.02 KiB | 522.00 KiB/s, done.
From github.com:username/repo
3f6a2c1..a92d44e main -> origin/main
Updating 3f6a2c1..a92d44e
Fast-forward
index.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
The Divergent Branches Warning
If you haven’t configured a reconciliation strategy, modern Git (2.27+) prints this warning every time your local and remote branches have both moved forward independently:
$ git pull
warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:
git config pull.rebase false # merge (the default strategy)
git config pull.rebase true # rebase
git config pull.ff only # fast-forward only
You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.
Git isn’t broken when you see this — it still completes the pull using the default merge strategy. It’s a deliberate nag, added because silently picking merge over rebase (or vice versa) had been a recurring source of surprise commit graphs. Pick a default and the warning disappears for good:
$ git config --global pull.rebase false
I default to pull.ff only on my own machine — it fast-forwards when possible and simply refuses the pull (rather than auto-merging) when histories have diverged, which forces me to consciously choose rebase or merge instead of letting Git silently create a merge commit I didn’t think about.
Merge vs Rebase Pull
| git pull (merge, default) | git pull –rebase | |
|---|---|---|
| History shape | Creates a merge commit joining both histories | Replays your local commits on top of the fetched ones — linear history |
| Commit graph | Branches and merges visible in git log --graph | Looks as if you’d made your commits after the latest remote changes, no merge commit |
| Safety on shared branches | Safe — never rewrites commits that exist elsewhere | Rewrites your local commit hashes; risky if you’ve already pushed them |
| Conflict resolution | Resolved once, in the merge commit | May require resolving the same conflict multiple times, once per replayed commit |
Rebase gives you a cleaner, linear log, but only rebase commits that haven’t been pushed anywhere else — rewriting shared history is exactly the scenario that produces the rejected-push and force-push situations covered in Git Push.
How the Code Works
git pull=git fetch(download new commits/refs) + a merge or rebase (integrate them into your current branch).pull.rebase falseuses merge — Git’s traditional default, creates a merge commit when histories diverge.pull.rebase truereplays your local unpushed commits on top of the fetched ones instead of merging.pull.ff onlyrefuses to pull at all if a fast-forward isn’t possible, forcing you to decide explicitly rather than auto-merging.
FAQs
What’s the difference between git pull and git fetch?
git fetch downloads new commits and updates remote-tracking branches like origin/main, but leaves your current branch untouched. git pull does that, then immediately merges or rebases the fetched changes into your current branch.
Why do I get merge conflicts on pull?
Because the remote and your local branch each changed the same lines of the same file since you last synced. Git can’t automatically decide which version is correct, so it pauses and asks you to resolve the conflict manually before completing the pull.
Is rebase always better than merge for pulling?
No, it’s a tradeoff. Rebase gives a cleaner history but rewrites commit hashes, which is dangerous on a branch others are also pulling from. Many teams default to merge for shared branches and allow rebase only on personal feature branches.
See Also: This Site’s Git Command Guide
This post is part of a 13-part Git command guide on this site:
- Git Init — starting a brand-new repository
- Git Clone — copying an existing repository
- Git Add — staging specific files for a commit
- Git Add . (All) — staging all changes at once
- Git Commit — saving staged changes to the repository
- Git Status — checking what’s changed before you commit
- Git Branch — creating, listing, and renaming branches
- Git Checkout — switching branches and restoring files
- Git Push — sending your commits to a remote
- Git Log — reading commit history
- Git: Delete Last Commit — undoing a commit safely
- Git – Autocorrect Spelling — typo recovery and productivity config
Conclusion
The divergent-branches warning is one of the more useful nags Git has added in recent years — it’s pushing you toward an explicit decision you were making implicitly anyway. Set pull.rebase or pull.ff once, globally, and move on. Once your local branch is current, reviewing what actually changed is next, in Git Log.