Git Push Error Solved: How to Fix ‘Failed to Push Some Refs’ in Simple Steps

Git Push Error Solved: How to Fix ‘Failed to Push Some Refs’ in Simple Steps
Git Push Error Solved: How to Fix ‘Failed to Push Some Refs’ in Simple Steps

Learn how to resolve the "Failed to Push Some Refs" error in Git with this step-by-step guide. Explore beginner, intermediate, and advanced solutions, including fixing merge conflicts and using force push and rebase.

You finish a chunk of work, run git push, and Git answers with ! [rejected] and error: failed to push some refs. The first time it happens it feels like something’s broken. It isn’t. Git is stopping you from throwing away work.

Here’s the whole thing in one sentence: the remote branch has commits your local branch doesn’t have yet. Someone pushed while you were heads-down, or you rewrote your own history, and now the two sides have split. Pushing would drop those remote commits, so Git refuses. Bring the remote’s work into your branch and the push goes through. Let’s walk it.

Table of Contents

Introduction to Git and the Push Process

When you run git push, Git sends your local commits up to a remote (GitHub, GitLab, a bare repo on your own server) so your teammates, or just future-you on another machine, can pull them down. The key detail: push only moves commits. Anything you haven’t committed stays on your machine and has no bearing on the push at all.

Hold onto that point. A lot of advice about this error gets it wrong, and this is where it goes wrong.

Understanding the ‘Failed to Push Some Refs’ Error

Git usually tells you exactly what’s wrong right under the rejection: (non-fast-forward). That’s the diagnosis. A fast-forward push is one where your branch simply adds new commits on top of what the remote already has, so the remote can slide its pointer forward to match yours. When the remote has commits you don’t, there’s nothing to fast-forward to. As the Git docs put it, pushing anyway “will lose history,” so Git rejects it instead.

Picture two people on one branch, both starting from the same commit. Your teammate pushes first. Now the remote sits one commit ahead of you. You commit your own work and push, and Git stops you: your history and the remote’s have diverged. You need their commit in your branch before yours can land.

Common Causes of the Error

Someone pushed before you did

The classic case. A teammate, or you from another laptop, pushed to the same branch after your last pull. The remote moved ahead, your local branch didn’t, and the two have diverged.

You rewrote your own local history

If you amended, squashed, or rebased commits you’d already pushed, your local branch no longer descends cleanly from the remote tip. Git sees divergence even when you’re the only author. This is the situation where force pushing eventually comes up, carefully.

First push to a branch that isn’t empty

Create a repo on GitHub with a README or license file, then push a local repo you started separately, and you hit the same wall. The remote already holds a commit your history never included.

One thing that is not a cause: uncommitted changes in your working directory. Push only deals with commits, so unsaved or unstaged files are simply ignored during a push. Committing more of them won’t clear a non-fast-forward rejection. Only syncing with the remote will. Keep that in mind as we go, because the fix is about history, not about your working tree.

Fixing the Error: Beginner Solutions

First, get your own work committed

Before you pull anything down, make sure your work is safe, so the sync can’t clobber it. Check what’s in your tree:

HTML
git status

Commit anything you want to keep:

HTML
git add .
git commit -m "Commit message"

(You could git stash instead, but committing is easier to reason about.) Now try the push:

HTML
git push origin your-branch-name

If it lands, you simply hadn’t committed yet and there was no real divergence. If Git still answers with non-fast-forward, the remote is genuinely ahead of you, and no amount of committing changes that. On to the next step.

The real fix: git pull

When the remote is ahead, you pull its commits into your branch first, then push:

HTML
git pull origin your-branch-name

By default this fetches the remote commits and merges them with yours, adding a merge commit if the histories diverged. Once your branch holds the remote’s work plus your own, the push is a clean fast-forward:

HTML
git push origin your-branch-name

Most of the time, that’s the entire fix.

Intermediate Techniques to Fix the Error

Resolving Merge Conflicts

Sometimes the pull can’t merge on its own, because you and the remote changed the same lines. Git pauses and hands the decision to you:

  1. Open the conflicting files in your editor.
  2. Look for the conflict markers (e.g., <<<<<<< HEAD) that indicate the conflicting sections.
  3. Decide which side to keep, or stitch both together by hand.
  4. Once a file looks right, stage it:
HTML
git add conflicted-file

Then finish the merge by committing the result:

HTML
git commit -m "Resolved merge conflicts"

With the conflicts settled, push again:

HTML
git push origin your-branch-name
Using Git Pull with Rebase

A merge pull leaves a merge commit every time histories diverge. If you’d rather keep a straight, linear history, rebase instead:

HTML
git pull –rebase origin your-branch-name

This fetches the remote commits, then replays your local commits on top of them, as if you’d written yours after theirs. You still resolve conflicts if any show up (fix the file, git add it, then git rebase --continue). When it finishes, push:

HTML
git push origin your-branch-name

One honest caveat: rebase only commits you haven’t shared yet. Rebasing commits other people have already pulled rewrites the ground under them.

Advanced Solutions: Force Pushing and Rebasing

Force Push: When and How to Use It

Everything above brings the remote’s work into your branch. Force pushing does the reverse: it tells the remote to drop what it has and take your version instead.

HTML
git push –force origin your-branch-name

The Git docs are blunt about this: --force disables the safety checks and “can cause the remote repository to lose commits.” Use it only when you meant to rewrite history you own, for example after squashing commits on your own feature branch that nobody else is building on. On a shared branch, a force push silently deletes your teammates’ commits from the remote, and that’s not something you undo casually.

There’s a safer version worth defaulting to: git push --force-with-lease. It only forces the push if the remote ref is still where you last saw it, so if someone pushed after your last fetch, the command refuses instead of steamrolling their work. Reach for --force-with-lease first, and save plain --force for the rare moment you truly mean “mine wins, no questions asked.”

Rebasing to Avoid Merge Conflicts

When your branch has drifted well behind the remote, rebasing keeps things tidy by replaying your commits on the current remote tip rather than tying the two together with a merge commit:

HTML
git pull –rebase origin your-branch-name

Work through any conflicts as they surface, then push:

HTML
git push origin your-branch-name

If you’d already pushed the commits you just rebased, this is the push where you’d reach for --force-with-lease from above. If you were only catching up before ever pushing, a normal push lands fine.

Preventing the Error: Best Practices

You’ll never kill this error entirely, but you can make it rare:

  • Pull (or at least fetch) before you start work and again before you push, so you’re always building on the latest remote commits.
  • Talk to your team so two people aren’t reshaping the same files on the same branch at the same time.
  • Work on feature branches instead of pushing straight to the main branch, so divergence stays small and easy to reconcile.
  • Lean on git pull --rebase for everyday syncing to keep history readable, but stop rebasing the moment commits are shared.
Conclusion

“Failed to push some refs” isn’t a broken setup. It’s Git refusing to lose commits on your behalf. The remote is ahead of you; pull its work in, resolve any conflicts, and push. Save force pushing (ideally --force-with-lease) for history you own that nobody else has pulled. Do that, keep pulling before you push, and this one quietly stops showing up.

Next: Remove Git Init: Undoing Git Initialization Guide

Leave a Comment

Your email address will not be published. Required fields are marked *


Scroll to Top