Pulling Changes (git pull)
git pull is the everyday command for bringing in remote changes. It is really two commands rolled into one: a git fetch followed by a git merge (or git rebase). That convenience comes with a small cost — it commits you to the integration immediately. Knowing what pull does under the hood prevents surprises.
The simplest pull
git pull # 1. Fetches commits from origin (or the upstream of your current branch) # 2. Merges them into your current branch # Together they bring your branch up to date with the remote
What pull is really doing
git pull = fetch + integrate
# 'git pull' is approximately this: git fetch origin git merge origin/<current-branch> # Or, with pull.rebase=true: git fetch origin git rebase origin/<current-branch>
Merge vs rebase on pull
git pull(default) — fetches, then merges. Creates a merge commit if needed.git pull --rebase— fetches, then rebases your local commits on top of the remote.git pull --ff-only— fetches; only succeeds if fast-forward is possible.
Pick your default
# Always rebase on pull (linear local history) git config --global pull.rebase true # Always fast-forward only (refuse if not possible) git config --global pull.ff only # Default (merge if needed) git config --global pull.rebase false
Common pull scenarios
Up-to-date — nothing happens
git pull # Already up to date.
Fast-forward — your branch catches up
git pull # Updating c204c1d..1f9ab2c # Fast-forward # src/login.js | 5 +++-- # 1 file changed, 3 insertions(+), 2 deletions(-)
Merge — diverged from remote
Both you and the remote have new commits
git pull # (your editor opens to confirm merge commit message) # Auto-merging src/login.js # Merge made by the 'recursive' strategy.
Conflicts — manual intervention
Both sides changed the same lines
git pull # CONFLICT (content): Merge conflict in src/login.js # Automatic merge failed; fix conflicts and then commit the result. # Resolve manually, then: git add src/login.js git commit
Aborting a pull
# If 'git pull' produced conflicts and you want out: git merge --abort # for default merge-style pull git rebase --abort # for rebase-style pull
Pulling a specific branch
git pull origin main git pull upstream develop # Useful when your current branch's upstream differs from what you want
Pull with options
--rebase— rebase instead of merge.--ff-only— require fast-forward.--no-ff— always create a merge commit.--prune— also remove stale remote-tracking branches.--autostash— stash uncommitted changes before pulling and pop after.--no-rebase— even if the global default is rebase, this pull will merge.
The two-step alternative
Many experienced developers prefer the explicit two-step version. It gives you a chance to see what is coming before committing to the integration:
Cautious daily workflow
git fetch git status # see ahead/behind git log HEAD..origin/main --oneline # what's new on the remote? # If happy: git merge origin/main # or: git rebase origin/main
Pulling with uncommitted changes
Use --autostash
# You have local edits but want to pull. --autostash handles it. git pull --autostash # Equivalent to: git stash git pull git stash pop
Common errors
"There is no tracking information for the current branch" — set an upstream:
git push -u origin <branch>."Your local changes would be overwritten by merge" — stash, commit, or discard before pulling.
"Pulling without specifying how to reconcile divergent branches" — set
pull.rebaseorpull.ffexplicitly.
git config --global pull.rebase true and git config --global rebase.autoStash true. The result: git pull always produces a linear local history with no merge commits, and never errors out on stashable changes.