How to fix fatal: Not possible to fast-forward, aborting. in Git
This error occurs when Git cannot perform a fast-forward merge during a pull operation because your local branch and the remote branch have diverged. You have local commits that are not on the remote, and the remote has commits you don't have locally.
Quick fix
Fixes fatal: Not possible to fast-forward, aborting.
# Fetch the latest changes without merging
git fetch origin
# See how your branch differs from the remote
git log --oneline --graph HEAD origin/main- Understand the current state of your branches
- Pull with rebase (recommended for most cases)
- Pull with merge (creates a merge commit)
- Stash local changes, pull, then reapply
# Fetch the latest changes without merginggit fetch origin# See how your branch differs from the remotegit log --oneline --graph HEAD origin/mainfatal: Not possible to fast-forward, aborting.
What this error means
The "fatal: Not possible to fast-forward, aborting" error indicates that Git cannot cleanly apply remote changes to your local branch without creating a merge commit. This happens when the commit histories of your local and remote branches have diverged. In Git, a "fast-forward" merge is the simplest type of merge. It occurs when your local branch can simply move its pointer forward to match the remote branch because there are no new local commits. Think of it like moving a bookmark forward in a book you're reading together with someone else. However, when you have made local commits that don't exist on the remote, and the remote also has new commits, Git can't simply move the pointer forward. The branches have "diverged" and need to be reconciled through either a merge or a rebase. This error commonly appears when: - You have the `pull.ff only` configuration enabled (Git's default since version 2.27) - You're using `git pull --ff-only` explicitly - Multiple developers are working on the same branch - You've made local commits and someone else pushed changes to the remote
Typical symptoms
- Running 'git pull' fails with 'fatal: Not possible to fast-forward, aborting'
- Pull operations that previously worked now fail with this message
- Error appears after making local commits on a shared branch
- CI/CD pipelines fail during git pull steps
- Error occurs after a colleague pushed changes to the same branch
Common causes
- Local branch has commits that don't exist on the remote branch
- Remote branch has commits that don't exist in your local branch
- Git configuration has 'pull.ff only' set (default since Git 2.27)
- Using 'git pull --ff-only' explicitly which prevents merge commits
- Another developer force-pushed to the branch, rewriting history
- Branch was rebased or amended after you pulled it
- Working on a shared branch where multiple people are committing
How to fix "fatal: Not possible to fast-forward, aborting."
First, examine the relationship between your local and remote branches:
# Fetch the latest changes without merging
git fetch origin
# See how your branch differs from the remote
git log --oneline --graph HEAD origin/mainReplace main with your branch name. This shows you:
- Your local commits (on your branch)
- Remote commits (on origin/branch)
- Where they diverged
Example diverged output:
* abc1234 (HEAD -> main) Your local commit
| * def5678 (origin/main) Their remote commit
|/
* 789abcd Common ancestorIf you see a fork like this, your branches have diverged and need to be reconciled.
The cleanest solution is to rebase your local commits on top of the remote changes:
git pull --rebase origin mainOr simply:
git pull --rebaseWhat this does:
1. Fetches remote changes
2. Temporarily removes your local commits
3. Applies the remote commits
4. Replays your local commits on top
Result: A clean, linear history without merge commits.
If you encounter conflicts during rebase:
# Fix conflicts in the affected files, then:
git add <fixed-files>
git rebase --continue
# Or abort if you want to try a different approach:
git rebase --abortIf you prefer to keep a record of the branch divergence, use a merge:
# Explicitly allow merge commits
git pull --no-ff origin mainOr fetch and merge separately:
git fetch origin
git merge origin/mainWhat this does:
Creates a merge commit that combines both lines of development.
Pros:
- Preserves the exact history of what happened
- Easier to resolve complex conflicts
- Can be undone with a single git revert
Cons:
- Creates extra merge commits
- History can become harder to read
If you have uncommitted changes preventing the pull:
# Save your uncommitted changes
git stash
# Pull the remote changes
git pull
# Reapply your stashed changes
git stash popNote: This only helps with uncommitted changes. If you have local commits, use one of the other approaches.
If you have both uncommitted changes AND local commits:
# Stash uncommitted changes first
git stash
# Then rebase your commits
git pull --rebase
# Finally, restore your uncommitted changes
git stash popTo avoid this error in the future, configure Git to rebase by default when pulling:
For a specific repository:
git config pull.rebase trueFor all repositories (global):
git config --global pull.rebase trueAlternative: Allow merge commits during pull:
# Remove the ff-only restriction
git config pull.ff falseCheck your current pull configuration:
git config --get pull.ff
git config --get pull.rebaseAvailable pull.ff values:
- only - Only fast-forward (causes this error when not possible)
- true - Fast-forward when possible, otherwise merge
- false - Always create a merge commit
Warning: This discards local commit history. Only use if you're sure.
If your local history is very complicated and you want to start fresh:
# Save your current changes to a backup branch
git branch backup-my-work
# Reset your branch to match the remote exactly
git fetch origin
git reset --hard origin/main
# Cherry-pick specific commits from your backup if needed
git cherry-pick <commit-hash>Or, if you just want to preserve your file changes (not commits):
# Create a patch of your changes
git diff origin/main > my-changes.patch
# Reset to remote
git reset --hard origin/main
# Apply your changes as uncommitted modifications
git apply my-changes.patchThis gives you a clean slate with the remote history while preserving your work.
If someone force-pushed to the remote branch (rewrote history), you need special handling:
Check if the remote was force-pushed:
git fetch origin
git log --oneline origin/main # Look for unfamiliar commit hashesIf the remote was force-pushed and you have no local changes to keep:
git fetch origin
git reset --hard origin/mainIf you have local commits to preserve:
# Create a backup
git branch backup-before-force-push
# Rebase your work onto the new remote history
git fetch origin
git rebase origin/main
# If there are conflicts, resolve them and continue
git rebase --continuePrevent force-push issues in the future:
- Enable branch protection rules on your repository
- Require pull request reviews before merging
- Avoid using git push --force on shared branches (use --force-with-lease instead)
Advanced notes
Understanding Git's Pull Behavior:
Since Git 2.27, the default behavior changed. Git now warns you and may refuse to pull when it detects diverged branches. This is controlled by pull.ff:
# Check your Git version
git --version
# See the default behavior
git config --get pull.ffThe Three Pull Strategies:
1. `git pull --ff-only` (or pull.ff = only)
- Only succeeds if fast-forward is possible
- Safest option, prevents accidental merges
- Causes this error when branches diverge
2. `git pull --rebase` (or pull.rebase = true)
- Rebases your local commits on top of remote
- Creates linear history
- May require conflict resolution for each commit
3. `git pull --no-ff` (or pull.ff = false)
- Always creates a merge commit
- Preserves branch structure
- Can make history harder to read
Team Workflow Recommendations:
For teams, consider these configurations in your .gitconfig or project documentation:
# Recommended: Rebase for pull, but protect against mistakes
git config --global pull.rebase true
git config --global rebase.autoStash trueThe rebase.autoStash option automatically stashes uncommitted changes before rebasing and restores them after.
Interactive Rebase for Complex Situations:
If you need more control, use interactive rebase:
git fetch origin
git rebase -i origin/mainThis lets you:
- Reorder commits
- Squash multiple commits into one
- Edit commit messages
- Drop unwanted commits
When to Use Merge vs Rebase:
| Scenario | Recommended Approach |
|----------|---------------------|
| Feature branch into main | Merge (preserves feature context) |
| Updating feature branch from main | Rebase (keeps feature commits together) |
| Shared branch with teammates | Merge (safer for collaboration) |
| Personal branch / cleanup | Rebase (cleaner history) |
| After code review | Squash merge (single commit per feature) |
Frequently asked questions
- What does "fatal: Not possible to fast-forward, aborting." mean?
- The "fatal: Not possible to fast-forward, aborting" error indicates that Git cannot cleanly apply remote changes to your local branch without creating a merge commit. This happens when the commit histories of your local and remote branches have diverged. In Git, a "fast-forward" merge is the simplest type of merge.
- How do I fix "fatal: Not possible to fast-forward, aborting."?
- This error occurs when Git cannot perform a fast-forward merge during a pull operation because your local branch and the remote branch have diverged. You have local commits that are not on the remote, and the remote has commits you don't have locally.
- What causes "fatal: Not possible to fast-forward, aborting."?
- Local branch has commits that don't exist on the remote branch Remote branch has commits that don't exist in your local branch Git configuration has 'pull.ff only' set (default since Git 2.27)
- Is the "fatal: Not possible to fast-forward, aborting." error serious?
- It is a low-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐Git Official Documentation
- ๐ฌ
- ๐
- ๐
- ๐Dealing with non-fast-forward errors - GitHub Docs(Official Docs)
- ๐
- ๐ฌgit pull stop working with fatal error - GitHub Community(Stack Overflow)