git pull is a compact wrapper around two operations. By default it
runs fetch (download updates) and then merge (merge into the
current branch).
pull or fetch + merge?
Technically git pull = git fetch && git merge FETCH_HEAD.
Many developers prefer to do these steps separately:
git fetchto see what arrived without touching the local branch.git log origin/main..mainto check the difference.git mergeorgit rebaseto integrate deliberately.
This gives you a pause between "got data" and "changed local branch." Useful on complex repositories.
--rebase vs merge
By default pull does a merge. The alternative is rebase:
git pull --rebase
This fetches the remote commits, then rewrites your local commits as if you had made them on top of the fresh remote ones. History stays linear, with no merge commits.
Which is better is a debate of decades. A practical rule:
- rebase for your own feature branch before sharing it.
- merge for shared branches (main, master).
- Set the default with config:
git config --global pull.rebase true.
Without an explicit setting, Git 2.27+ warns about strategy ambiguity
on every git pull. The pull still works (merge), but the warning
is there to make you choose deliberately. Set pull.rebase or
pull.ff in config and the warning goes away.
--ff-only
The safest option:
git pull --ff-only
Fetches updates only if fast-forward is possible. If you have local commits that are not merged, it refuses and you resolve it manually (merge or rebase). This prevents accidental merge commits from habit.
What physically happens
git fetch origindownloads all new objects into.git/objects/and updatesorigin/<branches>(these are refs/remotes/origin/...).- Takes the remote tracking branch (
origin/main) and compares it with the local one (main). - Runs merge (or rebase) of FETCH_HEAD into the current branch.
Local history is written only in step 3. Before that, git fetch
can be called as many times as you want. It is safe.
Pitfalls
git pullwith unstaged changes in files the remote also modifies will fail with an error. Fix: stash before pull, or commit first.- Without a tracking branch,
git pullwith no arguments does not work. You need to be explicit:git pull origin main. git pull --rebaseon a branch with already-pushed commits rewrites their SHAs. The next push will require--force-with-lease. Do not do this on branches other people are looking at.