C.W.K.
Stream
Lesson 02 of 05 · published

Pull Is Fetch Plus Integration

~20 min · pull, merge, rebase

Level 0Untracked Rookie
0 XP0/47 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

git pull is two operations, not one

git pull is shorthand for git fetch followed by an integration step — by default a merge, optionally a rebase. That second step is where confusion lives. Without thinking about it, git pull will create merge commits in your local branch when there is divergence, which is rarely what most developers actually want for short-lived feature work.

Two integration choices, both legitimate. Merge joins your branch with the upstream changes by creating a merge commit if needed. Preserves divergence in history. Good when the divergence is meaningful (long-lived integration branches, releases). Rebase replays your local commits on top of the upstream tip. Result: linear history. Good for short-lived feature work where the divergence is "I worked while someone else also worked" rather than a structural fork.

The recommended modern default is to set pull.rebase = true globally and use plain git pull for daily work. Linear history is easier to read, bisect is cleaner, and reviewers see one chain instead of "merge of main into feature" noise. When the situation calls for a true merge (release branch integration, big-feature handoff), use git merge explicitly. git pull is for the routine case.

Two failure modes to recognize. Pull with uncommitted changes: Git refuses if integration would touch the same files. The fix is commit (or stash) first, pull second. Pull rebase mid-conflict: rebase pauses on each conflicting commit, asks you to resolve and git rebase --continue. If a rebase pull goes sideways, git rebase --abort rewinds you to before the pull, fully reversible.

Code

Daily-grade pull patterns·bash
# Configure once, then forget:
git config --global pull.rebase true
git config --global rebase.autoStash true   # auto-stash dirty tree

# Routine pull on a feature branch:
git pull           # = fetch + rebase (with global config above)

# One-off pull as merge (override the rebase default):
git pull --no-rebase

# Force fetch+nothing (no integration), then choose manually:
git fetch
git rebase origin/main      # or git merge origin/main
When pull goes wrong·bash
# Dirty tree before pull?
git stash push -u -m "pre-pull WIP"
git pull
git stash pop      # or git stash apply

# Conflicts during rebase pull:
# Edit conflicting files, then:
git add resolved-file
git rebase --continue
# ... or bail out entirely:
git rebase --abort

# After a confused merge pull, undo:
git reset --merge ORIG_HEAD

External links

Exercise

On a real repo, set pull.rebase = true globally and rebase.autoStash = true. Engineer a divergence: make a local commit, push from another clone (or simulate by editing the remote-tracking ref), then git pull on the original. Inspect the result with git log --oneline --graph and confirm linear history. Reset, set pull.rebase = false for the repo, repeat the divergence, pull again, and observe the merge commit. Decide which policy fits which kind of branch in your work.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.