Overview
Git 2.27+ warns on git pull if you haven’t told it how to handle divergent histories:
- Merge (default historically): create a merge commit
- Rebase: replay your local commits on top of upstream
- Fast-forward only: refuse to merge; only update when no divergence exists
You can silence the warning and set a safe default by configuring one of these behaviors globally or per-repository.
Quickstart (choose one default)
Pick one strategy and set it globally. You can override per repo or per command.
- Merge (keeps merge commits)
- Command:
git config --global pull.rebase false
- Command:
- Rebase (linear history; common for feature branches)
- Command:
git config --global pull.rebase true - Optional quality-of-life:
git config --global rebase.autoStash true
- Command:
- Fast-forward only (CI-safe; refuse implicit merges)
- Command:
git config --global pull.ff only
- Command:
One-off override when pulling:
git pull --rebasegit pull --no-rebasegit pull --ff-only
Minimal working example (reproduce and fix)
This demonstrates the warning and how to resolve it.
# Terminal A: create a repo and publish it
mkdir demo && cd demo && git init -b main
printf "a\n" > file.txt
git add file.txt && git commit -m "init"
# Create a bare remote to simulate origin
cd .. && git clone --bare demo demo.git
cd demo && git remote add origin ../demo.git && git push -u origin main
# Terminal B: clone elsewhere and diverge
cd .. && git clone demo.git demo-b && cd demo-b
printf "b\n" >> file.txt && git commit -am "b from clone B" && git push
# Terminal A: make a conflicting local commit and pull
cd ../demo
printf "a2\n" >> file.txt && git commit -am "a2 from clone A"
# This pull may warn that you must specify how to reconcile
git pull origin main # shows the warning on modern Git
# Fix by choosing a policy; e.g., rebase
git config pull.rebase true
# Try again (or future pulls auto-rebase)
git pull --rebase
If you prefer a universal setting, use --global:
git config --global pull.rebase true
# or
git config --global pull.ff only
# or
git config --global pull.rebase false
Choosing a strategy
| Strategy | Behavior | Pros | Cons | Recommended for |
|---|---|---|---|---|
| Merge | Creates a merge commit when both sides changed | Preserves exact history; simple | Extra merge commits; noisier git log | Shared branches where merge commits matter |
| Rebase | Replays local commits atop upstream | Linear history; easier bisect & revert | Rewrites local commits; care needed on shared branches | Feature/topic branches; daily development |
| FF-only | Refuses pulls unless fast-forward possible | Avoids accidental merges; CI-friendly | Requires explicit merge/rebase when diverged | CI/CD, protected branches |
Step-by-step fixes
- Decide a default policy
- Individual devs often prefer rebase for linear history.
- CI and protected branches prefer fast-forward only.
- Set the default
- Rebase:
git config --global pull.rebase true - Merge:
git config --global pull.rebase false - FF-only:
git config --global pull.ff only
- Optionally set per-repo policy (overrides global)
# inside the repo
git config pull.rebase true
# or
git config pull.ff only
- Use one-off flags when needed
git pull --rebase # just this time
git pull --no-rebase # just this time
git pull --ff-only # just this time
- Verify your config and behavior
git config --show-origin --get pull.rebase
git config --show-origin --get pull.ff
git pull --verbose
DevOps recommendations
- Developer machines:
git config --global pull.rebase true; addrebase.autoStash trueto reduce conflicts with local changes. - CI jobs: Avoid implicit merges. Prefer either:
git fetch --tags --pruneand thengit merge --ff-only origin/main, orgit pull --ff-onlyif you must use pull.
- Protected release branches: enforce fast-forward merges in server settings and on clients use
pull.ff onlyto block accidental merge commits.
Pitfalls and safeguards
- Rebasing public commits: Avoid rebasing commits already pushed to shared branches unless your team agrees; it rewrites history and can force others to reconcile.
- Merge noise: Using merge by default on busy branches can create many merge commits; consider rebase or require PR squashes.
- FF-only failures: If
--ff-onlyfails, explicitly choose--rebaseor create a merge commit via PR to resolve divergence. - Work-in-progress changes: With rebase, stash or enable
rebase.autoStash trueto avoid interruptions. - Signed commits: Rebasing re-creates commits; verify signatures if your workflow requires GPG/SSH-signed commits.
- Submodules: Rebases can be trickier with submodules; update submodules explicitly after pull.
- Hooks and automation: Ensure client-side hooks don’t assume merge vs rebase; they run at different times.
Performance notes
- Network first:
git pullisfetch + merge/rebase. Most time is network I/O; optimizing fetch (e.g.,--depth=1clones for CI) often yields the biggest gains. - Rebase cost: Rebasing replays your local commits; typically cheap if you have few local commits. Large, conflicting series can be slower.
- Merge cost: Creating a merge commit is O(changes), similar to rebase for small local deltas.
- Caching: Keep repositories lean; periodically run
git gc --aggressivein maintenance windows to reduce pack fragmentation. - Shallow workflows (CI): Prefer
git clone --depth=1orgit fetch --depth=1and--ff-onlyto minimize history transfer.
Troubleshooting
- Still seeing the warning after setting config? Check scope:
- Per-command flags override repo config, which overrides global config.
- Inspect with
git config --list --show-originto find conflicting entries.
- Undo a rebase in progress:
git rebase --abort. - Undo after a completed rebase/merge: use
git reflogto find the previous HEAD, thengit reset --hard <sha>(ensure you won’t lose unpushed work).
FAQ
What does “reconcile divergent branches” mean? Your local branch and the remote both have new commits. Git needs to know whether to merge, rebase, or refuse.
What’s the safest default for CI?
pull.ff onlyso builds fail fast instead of creating implicit merges.Can I set different policies for different repos? Yes. Omit
--globaland rungit config pull.rebase true(orpull.ff only) inside a repository.How do I silence the warning without changing history behavior? Pick the matching config: Set
pull.rebase falseto keep merge behavior, or setpull.rebase trueto always rebase, orpull.ff onlyto forbid merges.Does this change server-side behavior? No. These are client-side settings that only affect your
git pull.