Introduction

This error means the remote branch already contains commits your local branch does not have. On an unprotected branch you might overwrite history with a force push, but protected branches in GitHub, GitLab, and Azure DevOps correctly block that path. The fix is to integrate the remote commits first, then push a fast-forward result.

Symptoms

  • git push fails with non-fast-forward or failed to push some refs
  • A follow-up git push --force is rejected by branch protection
  • The problem starts after another engineer pushed to the same branch or after you amended or rebased local commits
  • CI or pull request checks still point to the remote branch while your local branch history has diverged

Common Causes

  • Someone pushed new commits to the remote branch before you pushed yours
  • You rewrote local history with git commit --amend or git rebase after an earlier push
  • Multiple engineers are pushing to the same shared feature branch
  • You are pushing directly to a protected integration branch that only allows pull requests

Step-by-Step Fix

  1. 1.Inspect how far your branch diverged
  2. 2.Confirm whether you only need to replay your local commits or whether the branch now has unrelated remote work you must review first.
bash
git fetch origin
git status
git log --oneline --graph --decorate HEAD..origin/feature-branch
git log --oneline --graph --decorate origin/feature-branch..HEAD
  1. 1.Rebase onto the remote branch if your local commits should stay on top
  2. 2.This is the usual fix for a personal feature branch or a branch where your commits should remain linear after newer remote work.
bash
git fetch origin
git rebase origin/feature-branch
git push origin feature-branch
  1. 1.Use a merge if the branch is shared and you want the safest reconciliation
  2. 2.A merge commit avoids rewriting local commit hashes again and is often easier when several people are already collaborating on the same branch.
bash
git fetch origin
git merge origin/feature-branch
git push origin feature-branch
  1. 1.Switch to a pull request flow if direct pushes are intentionally blocked
  2. 2.If the remote platform rejects all direct updates to the target branch, push your fixes to a separate branch and merge through review instead of fighting branch protection.
bash
git switch -c fix/non-fast-forward-recovery
git push -u origin fix/non-fast-forward-recovery

Prevention

  • Run git fetch origin before starting a rebase, amend, or release push on shared branches
  • Prefer short-lived feature branches over long-lived shared branches with many direct pushes
  • Use pull requests for protected branches instead of planning around force pushes
  • If history rewriting is allowed on a branch, use git push --force-with-lease rather than plain --force