non-fast-forward

Git push rejected non-fast-forward: the fix that actually works

Your local branch diverged from remote after amend or rebase. Force push with lease to sync. Here's the exact command and why it's safe.

Yeah, that error is annoying. You amended a commit or rebased, then git push slaps you with rejected, non-fast-forward. You're not alone—I've had clients lose an afternoon to this. But the fix is one command, and I'll show you the safe version.

The fix: force push with lease

Run this:

git push --force-with-lease

That's it. If you're on a branch that tracks a remote (like main or feature/foo), this will overwrite the remote branch with your local history. The --force-with-lease part is the key—it checks that the remote branch hasn't changed since you last fetched. If someone else pushed to it, the push fails, which is what you want.

If you want to be extra explicit about the branch:

git push --force-with-lease origin feature/foo

Why this works

Here's what happened. When you amend or rebase, you're rewriting commit history. Git creates new commits with new hashes. Your remote still has the old commits. Git sees two different histories—your local and the remote—and refuses to merge them because they've diverged. The --force flag tells git to overwrite the remote branch, but without the -with-lease part, it'll overwrite even if someone else added commits. That's a footgun. The lease prevents that.

Real story: I had a client last month who did a plain git push --force and blew away a colleague's commit that was pushed 10 minutes earlier. Took an hour to recover with reflog. Don't be that guy.

When to use plain --force instead

Sometimes --force-with-lease fails with a message like "stale info" or "remote ref updated since last fetch". That's rare if you've just fetched, but if it happens, you can do:

git fetch origin
git push --force-with-lease

If that still fails, then someone did push. Don't force it—rebase your work onto the remote branch:

git fetch origin
git rebase origin/feature/foo
git push --force-with-lease

That integrates their changes and then force-pushes your rewritten history cleanly.

Less common variations

You're on a protected branch (like main)

GitHub and GitLab often block force pushes to main. You'll get a message like "protected branch hook declined". You have two options: push to a feature branch and open a PR, or temporarily disable protection (if you have admin rights). I'd push to a branch—it's cleaner and keeps the audit trail.

You rebased onto a remote branch that moved

If you rebased onto origin/main but then someone pushed to main, your local main is based on an old origin. The force push will clobber their new commit. Use the fetch + rebase approach above, then force push.

You're working with submodules

You rarely see this, but if you have a submodule and the submodule's commit reference changed, the parent repo push can reject non-fast-forward. Fix the submodule pointer first (git submodule update --remote) and commit that, then push.

Your remote is a bare repo on a server

If you're pushing to a server that has the branch checked out, you'll get "refusing to update checked out branch". That's not a non-fast-forward, but it's similar. You need to set receive.denyCurrentBranch to updateInstead on the server, or push to a non-checked-out branch.

Prevention: stop this from happening again

The real way to avoid this is to not rewrite public history. If you've already pushed a branch and others are using it, don't amend or rebase. Instead, add a new commit with a message like fixup! previous message or just a normal commit.

If you're working solo on a feature branch, you can amend and rebase to your heart's content—just remember you'll need the force push. To make it a habit, use this alias:

git config --global alias.pushf 'push --force-with-lease'

Then git pushf does the safe force push. No more typing the long command.

Also, get in the habit of fetching before you start amending. A quick git fetch will tell you if the remote moved. If it hasn't, you're safe to amend and force push. If it has, rebase first.

That's the whole deal. Next time you see non-fast-forward, you'll know exactly what to type and why it matters. Now go fix that branch.

Related Errors in Programming & Dev Tools
TS2307 TS2307: Cannot find module after setting up path aliases 0XC00002B5 Fixing STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5) in Windows apps 0X000000CF Fix ERROR_RING2_STACK_IN_USE (0X000000CF) on Windows 10/11 0X00000257 Fix ERROR_STACK_OVERFLOW_READ (0X00000257) in Windows

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.