Git Pull
Git pull downloads new commits from a remote branch and merges them into your current local branch in a single step.
Pull Is Fetch Plus Merge
git pull is really a convenience command that runs two operations back to back: git fetch, which downloads new commits and updates remote-tracking branches without touching your working files, followed by git merge, which integrates those newly fetched commits into your current branch. Understanding pull as two steps rather than one atomic action makes it much easier to reason about what is happening, and what can go wrong, when a pull produces unexpected results.
Because pull touches your working directory immediately, it can create merge commits or, in some configurations, trigger a rebase instead of a merge. This is one reason experienced developers sometimes prefer running fetch and merge (or fetch and rebase) as separate, deliberate steps rather than relying on the combined pull command, particularly on branches with a long or complicated history.
Fetch Alone: Looking Before You Leap
Fetching without merging
$ git fetch origin
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
Unpacking objects: 100% (9/9), 2.11 KiB | 108.00 KiB/s, done.
From github.com:acme/project
a3f1c9d..e77bc02 main -> origin/main
$ git log main..origin/main --oneline
e77bc02 Add rate limiting to the API
c4402fe Update dependency versionsAfter a plain fetch, your local main branch has not changed at all; only the remote-tracking reference origin/main has moved. This gives you a chance to inspect exactly what is new, using a range like main..origin/main, before deciding how to bring those commits into your own branch.
Running a Standard Pull
A typical pull with a fast-forward merge
$ git pull origin main
remote: Enumerating objects: 14, done.
From github.com:acme/project
a3f1c9d..e77bc02 main -> origin/main
Updating a3f1c9d..e77bc02
Fast-forward
README.md | 4 ++--
src/api.js | 22 +++++++++++++++++++---
2 files changed, 21 insertions(+), 5 deletions(-)When your local branch has no commits that the remote doesn't already have, Git performs what's called a fast-forward merge: it simply moves your branch pointer forward to match the remote, with no merge commit created. This is the cleanest, simplest outcome of a pull.
When Histories Diverge
If you have made local commits that the remote does not have, and the remote has commits you do not have, a fast-forward is impossible. Git falls back to a real merge, creating a new merge commit that ties both histories together. Depending on how the changed lines overlap, this may or may not require you to resolve conflicts by hand.
- Fast-forward: your branch has no new commits the remote lacks; the pointer simply advances
- Merge commit: both sides have new commits; Git creates a commit with two parents
- Conflict: both sides changed the same lines; you must edit the files and commit the resolution
- Rebase (with --rebase): your commits are replayed on top of the remote's commits instead of merging
Resolving a Pull Conflict
Handling a conflicting pull
$ git pull origin main
Auto-merging src/config.js
CONFLICT (content): Merge conflict in src/config.js
Automatic merge failed; fix conflicts and then commit the result.
$ git status
Unmerged paths:
both modified: src/config.js
# edit src/config.js to resolve the <<<<<<< markers, then:
$ git add src/config.js
$ git commit -m "Merge remote changes into config.js"