You run git push expecting your commits to fly up to GitHub, but instead you get a wall of text ending with error: failed to push some refs and a hint about non-fast-forward updates. It is a very common, confusing message for beginners.
The good news is that your commits are safe, nothing you wrote has been lost, and the fix is usually two commands. Git is refusing the push because the remote branch has moved ahead without you, and it wants you to integrate those changes first. This guide translates the scary message into plain English and fixes it properly, without dangerous shortcuts.
Quick Answer
The failed to push some refs non-fast-forward error means the remote branch contains commits your local branch does not have, so Git blocks the push to avoid overwriting them. Fix it by running git pull --rebase origin main (replacing main with your branch name) to bring your branch up to date, resolve any conflicts, and then run git push again. A regular git pull followed by git push also works.
Reading the Full Error Message
Beginners often stop reading at the word error, but Git’s message actually explains everything if you go line by line. A typical version looks like this:
! [rejected] main -> main (non-fast-forward)— the branch you tried to update was refused, and the reason in brackets is non-fast-forward.error: failed to push some refs to 'github.com:...'— the summary line. Some refs means one or more branches could not be pushed.hint: Updates were rejected because the tip of your current branch is behind its remote counterpart.— Git literally tells you the cause: the remote is ahead of you.hint: ... use 'git pull' before pushing again.— Git also tells you the intended cure right in the hints.
Non-fast-forward is the technical phrase at the heart of it. A fast-forward push is a simple slide forward, where the remote just moves its pointer ahead along commits it can reach from your branch. Your push is not a simple slide, because the remote has commits your branch cannot reach. Forcing it through would cut those commits off, so Git says no.
Why This Happens in Real Life
- A teammate pushed to the same branch. While you were coding, they finished first and pushed. The remote moved, and you did not.
- You pushed from another machine or location. Commits you made at home, or through the GitHub web editor, are on the remote but not on this computer.
- A pull request was merged. Merging on GitHub adds commits to the remote branch. If it was your own pull request, your local branch instantly falls behind the moment it merges.
- You rewrote local history. If you amended, rebased, or reset commits that were already pushed, your local line of history no longer matches the remote line, even if the code is nearly identical.
- Someone force pushed. If a teammate rewrote the remote branch, your local history and the remote history have genuinely split, and you should coordinate with them before fixing anything.
Most of these causes are everyday teamwork, not mistakes. If you are new to the platform, our walkthrough on getting started with GitHub as a complete beginner shows the normal pull and push rhythm that keeps this error rare.
Before You Fix: Inspect the Situation
- Run
git fetch originto update your view of the remote without touching your files. - Run
git statusand read whether you are behind, ahead, or diverged, and by how many commits. - Run
git log --oneline --graph --all -10to see a small map of how your branch and the remote branch split.
Fix 1: Pull With Rebase, Then Push (Clean and Popular)
- Make sure all your work is committed. Run
git statusand commit anything you want to keep, because rebasing works on commits. - Run
git pull --rebase origin main, replacingmainwith your branch name if you are pushing a different branch. - Git fetches the remote commits, moves your branch up to match them, then replays your local commits on top one at a time.
- If a conflict appears, open the file, fix it, stage it with
git add filename, and rungit rebase --continue. If you get stuck and want to abandon the attempt safely,git rebase --abortreturns you to where you started. - When the rebase completes, run
git push origin main. The push is now a clean fast-forward and will be accepted.
This is the method most experienced developers reach for on their own branches, because the resulting history is one straight, readable line. The official Git push documentation describes exactly why a non-fast-forward push is rejected by default, and why integrating first is the designed workflow.
Fix 2: Pull With Merge, Then Push (Simplest to Understand)
- Commit your work, just as in the rebase fix.
- Run
git pull origin main. Git fetches the new commits and merges them into your branch. - If there are conflicts, resolve them in your editor, stage the files with
git add, and complete the merge withgit commit. - Git may create a merge commit joining the two histories. That is normal and honest.
- Run
git push origin mainand watch it succeed.
Choose merge if rebase feels confusing, if your team prefers visible merge history, or if your commits are already shared with others. Both fixes are correct. The only wrong fix is the one that discards somebody’s commits, which brings us to the warning below.
The Dangerous Shortcut: Why Not Just Force Push?
Search this error online and you will quickly find someone suggesting git push --force. That command does make the error vanish, by overwriting the remote branch with your local version and deleting the remote commits you were missing. If those commits were a teammate’s work, their work disappears from the shared branch.
Force push has exactly one acceptable home: a branch that only you use, after you deliberately rewrote its history with amend or rebase, and ideally using git push --force-with-lease, which at least refuses if the remote moved unexpectedly since you last looked. On main or any shared branch, fixing a non-fast-forward rejection with force is never the right call. Pull first, always.
Common Mistakes to Avoid
- Force pushing a shared branch to silence the error. You may delete commits your team needs. Integrate with pull instead.
- Pulling with uncommitted changes everywhere. Commit your work or stash it with
git stashfirst, so the pull or rebase starts from a clean, predictable state. - Panicking and recloning the whole project. Recloning works but throws away your local setup and any unpushed commits you forgot about. Pulling in place is faster and safer.
- Typing the wrong branch name in the fix commands. If you are on
developor a feature branch, pull and push that branch, notmain. Check withgit branchif you are unsure. - Abandoning a conflict halfway. During a rebase or merge, finish the process or abort it cleanly. Leaving a repository mid-rebase and pushing later creates a second, harder problem.
- Assuming failed to push some refs means all branches failed. It may mean only one branch was rejected while others pushed fine. Read which ref was rejected before acting.
Conclusion
The failed to push some refs non-fast-forward error is Git refusing to destroy work, and once you read its hints, it even hands you the cure. Bring the remote changes into your branch with git pull --rebase or a plain git pull, resolve any conflicts that appear, and push again to get a clean fast-forward. Reserve force push for your own branches after intentional history rewrites, and never use it to bulldoze a shared branch. Make pulling a daily habit, at the start of work and before you push, and you will see this famous error less and less.
Frequently Asked Questions
Has my work been lost when I see this error?
No. A rejected push changes nothing on either side. Your local commits are still safely on your computer, and the remote commits are still safely on the server. The error simply pauses you until you combine the two sets of commits with a pull, after which the push succeeds with everything included.
What is the difference between this error and a merge conflict?
This error happens before any merging, at the push stage, when Git refuses to overwrite the remote. A merge conflict happens during a pull, merge, or rebase, when both sides changed the same lines. In fact, fixing this error with git pull can sometimes lead you into a merge conflict next, which you then resolve in your editor before pushing.
Should I use git pull or git pull –rebase for this fix?
Both work. A plain pull merges the histories and may add a merge commit, which is simple and safe for shared branches. Pull with rebase replays your commits on top for a straighter history, and suits branches that are yours alone. The GitHub overview of rebasing and merging can help you and your team pick one consistent style.
What does “some refs” mean? Which refs failed?
Refs are Git’s names for branches and tags. Some refs simply means at least one of the branches you tried to push was rejected. Look a few lines above the error for a line like ! [rejected] main -> main (non-fast-forward), which names the exact branch that failed, so you know exactly what to pull and push again.
How do I stop this error from happening so often?
Sync little and often. Run git pull when you start work, before you begin a new task, and right before you push. Keep feature branches short-lived, and communicate on busy shared branches. The more frequently you integrate small updates, the smaller and rarer non-fast-forward rejections become.


Leave a Reply