You ran git pull --rebase origin main to sync your feature branch and Git stopped mid-rebase with a conflict in src/config.ts — but the conflict shows changes you never made, or the diff markers contain code from three different developers’ commits merged into a confusing blob. After resolving and continuing, git log --oneline looks unfamiliar: your commit timestamps are changed, commits appear in a different order, and some commit messages are duplicated. The rebase replayed your local commits on top of the fetched origin/main, rewriting each commit’s SHA. This guide explains which parts are normal, which indicate a real problem, and how to recover if the rebase went wrong.
Common causes
Ordered by hit rate, highest first.
1. Long-running branch with many remote commits to replay over
The feature branch diverged from main 40 commits ago. git pull --rebase now replays each of your 10 commits on top of 40 new remote commits, with each replay potentially conflicting. The cumulative conflict noise is overwhelming.
How to spot it: git log --oneline HEAD..origin/main | wc -l — if this shows more than 10 new remote commits, the rebase will touch many stale context lines.
2. The same file was changed independently in multiple local commits
Your branch has three separate commits each touching src/config.ts. When replayed, each one may conflict with the remote’s version of that file, producing three separate conflict resolutions that are hard to reason about in isolation.
How to spot it: git log --oneline --follow -- src/config.ts on your local branch — if the file appears in more than one commit, expect multiple conflicts during rebase.
3. A previous git pull --rebase was aborted mid-way
A previous rebase was not finished or aborted with git rebase --abort, but the branch state was left inconsistent. The new git pull --rebase started from an already-modified state.
How to spot it: ls .git/REBASE_HEAD — if this file exists, a rebase is already in progress. git rebase --status will show the current state.
4. Merge commits in local history confused the rebase
Your local branch contains a merge commit (perhaps from a previous git pull without --rebase). git rebase cannot replay merge commits by default and silently drops them, potentially losing commits.
How to spot it: git log --oneline --merges HEAD...origin/main — if merge commits appear, they will be dropped during the rebase.
5. pull.rebase is set globally, so every git pull runs as rebase
git config --global pull.rebase true causes every git pull to rebase, even when the developer did not intend it. On branches where a merge would have been the right choice, the rebase rewrites history unexpectedly.
How to spot it: git config pull.rebase returns true. The developer ran git pull expecting a merge commit.
Shortest path to fix
Step 1: Abort the current rebase if it went wrong
git rebase --abort
This returns your branch to its pre-rebase state (the state before git pull --rebase started).
Step 2: Understand the divergence before retrying
git fetch origin
git log --oneline HEAD...origin/main --left-right
The --left-right flag shows which commits are local (left arrows) and which are remote (right arrows). Count and review each group before choosing a strategy.
Step 3: Use merge instead of rebase for widely-diverged branches
git pull --no-rebase origin main # creates a merge commit instead
On a feature branch, a merge commit is honest about the integration point and avoids per-commit conflicts.
Step 4: If you want rebase, squash local commits first
# Squash your local commits into one before rebasing
git rebase -i origin/main~0 # or use: git rebase -i HEAD~N
# Mark all but the first commit as 'squash'
# Then pull-rebase produces at most one conflict to resolve
git pull --rebase origin main
Step 5: Resolve the rebase one commit at a time
# During git pull --rebase, when a conflict appears:
git status # shows which files are conflicted
# Edit the conflicted files to resolve
git add src/config.ts
git rebase --continue --no-edit
Repeat for each replayed commit.
Step 6: Verify final state
git log --oneline -10
git diff origin/main
git status
Confirm no conflict markers remain (grep -r "<<<<<<" src/ should return nothing).
Prevention
- Keep feature branches short-lived — aim to merge within 3-5 days to minimize divergence before rebase.
- Set
pull.rebase = falseas the default and usegit pull --rebaseonly intentionally:git config --global pull.rebase false. - Avoid merge commits in local feature branches by rebasing against
mainfrequently:git fetch origin && git rebase origin/main— short rebases have fewer conflicts than long ones. - Squash or fixup “work in progress” commits before rebasing so each replayed unit is a coherent, independently-testable change.
- Configure
rerere.enabled = trueso Git remembers your conflict resolutions and auto-applies them if the same conflict appears again during the rebase. - Use
git fetch+git log HEAD..origin/mainto preview what is incoming before pulling, so you are not surprised by the rebase complexity. - For shared branches, always use
git pull --no-rebaseto avoid rewriting history that others may already have.
FAQ
Q: After completing the rebase, the commit timestamps all changed. Is that a problem? A: The author timestamps (when you originally wrote the code) are preserved. The committer timestamps change because each commit was re-applied. For most workflows this is fine; for audit trails that rely on committer time, use merge instead.
Q: git pull —rebase dropped one of my commits entirely. How do I recover it?
A: Run git reflog | head -20 to find the commit before the rebase started. Create a branch there and cherry-pick or merge the missing commit. See the Commits Disappeared After a Rebase article for a detailed walkthrough.
Q: Can I configure git pull to always ask before rebasing?
A: Not natively, but a pre-rebase hook can prompt you: create .git/hooks/pre-rebase with read -p "Rebase? [y/N]: " yn && [ "$yn" = y ].
Q: What is rerere and should I enable it?
A: rerere (Reuse Recorded Resolution) records how you resolved each conflict and auto-applies the same resolution if the identical conflict appears again. It is very useful for long rebases with repetitive conflicts. Enable it with git config --global rerere.enabled true.