[Git] Error: error: failed to push some refs to repo — How to Fix It

Summary

The message error: failed to push some refs to <repo> means your local branch diverged from the remote: the server has commits you don’t. Providers block non-fast-forward updates by default to protect shared history. Typical triggers include another user pushing first, working on the wrong branch name (main vs master), or a rebase/force-push upstream. The safe remedy is to fetch/pull (preferably with --rebase), resolve any conflicts, then push. Force pushes should be rare and coordinated.

Context

Git prevents you from overwriting remote history unless the update is a fast-forward. If your local tip lacks commits that are already on the remote, the push is rejected. This happens frequently on collaborative repos when two contributors modify the same branch, when CI rebases before merging, or when you created your branch off an outdated base. On Linux/macOS with Git ≥2.40, the recommended workflow is to rebase your local commits on top of the current remote branch, keeping a linear history. If the remote default branch changed names, align your local branch to match before pushing.

Probable Cause

  • Local branch is behind the remote. Another contributor pushed new commits to the same branch; your local history doesn’t include them, so your push would overwrite remote work. A fast-forward is impossible until you incorporate upstream changes.
  • Non-fast-forward policy blocks rewrite. Server settings (GitHub/GitLab) reject history rewrites on protected branches. If you rebased locally (rewriting commit IDs), your push conflicts with remote ancestry and is denied to avoid losing reviewed commits.
  • Branch name mismatch or wrong upstream. You’re on master while the remote uses main, or your origin upstream is set to a different branch. Pushing the wrong ref triggers rejections or silently targets the wrong history.

Quick Fix

  1. Confirm branch and upstream. Verify you’re on the intended branch and it tracks the correct remote.
git status
git branch -vv
  1. Fetch latest remote state. This updates your refs without merging yet.
git fetch origin
  1. Rebase your work onto the remote tip. Replace main with your branch name if different. Resolve conflicts as prompted.
  2. Linux/macOS: use your shell editor for conflicts; git rebase --continue to proceed.
  3. If your repo enforces merge commits, use git pull --rebase to keep local history linear while respecting server policies.

git pull --rebase origin main

  1. Push with upstream tracking. First push may need -u. If push still fails, recheck conflicts or branch names.

git push -u origin main

  1. Only if coordinated and safe: On a personal branch (not shared/protected) where you intentionally rewrote history, force-with-lease preserves safety by refusing to overwrite unexpected remote changes.

git push --force-with-lease origin main

  1. Fix branch name mismatch. If the remote uses main and you have master, rename and set upstream.

git branch -M main && git push -u origin main

Full Example

Scenario: Two developers edited README.md on main. Dev-B tries to push and gets the error because Dev-A pushed first.

$ git push origin main
To github.com:org/repo.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'github.com:org/repo.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes...

Resolution via rebase:

$ git fetch origin
$ git pull --rebase origin main
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
$ git status
# fix README.md, then mark resolved
$ git add README.md
$ git rebase --continue
$ git push origin main
Enumerating objects: 5, done.
To github.com:org/repo.git
   1c9b0f2..7a5d3ab  main -> main

Verification: Confirm linear history and branch alignment.

$ git log --oneline --graph --all
* 7a5d3ab Update README (Dev-B)
* 1c9b0f2 Update README (Dev-A)
* 0a12c77 Initial commit

Rebasing replayed Dev-B’s commit on top of Dev-A’s, producing a clean, fast-forwardable history. No force push was required, so shared branch protections remain intact.

Pitfalls & Debug

  • Symptom → Rebase loop or repeated conflicts. Fix → Abort and re-sync: git rebase --abort, then git fetch and re-attempt with smaller, well-scoped commits.
  • Symptom → Push rejected on protected branch. Fix → Open a PR from a feature branch; do not force-push to main on shared repos.
  • Symptom → Wrong branch name. Fix → Check default branch on remote; use git branch -M main and git push -u origin main.
  • Symptom → Upstream not set. Fix → git push -u origin <branch> to establish tracking; future git pull/push use defaults.
  • Symptom → Local history rewritten unintentionally. Fix → Prefer --force-with-lease (never plain -f) and coordinate with teammates.

Validation & Next Steps

After pushing, inspect history and remote alignment to ensure a clean graph and correct upstream.

git log --oneline --graph --decorate --all
git remote show origin

If the graph shows your commits atop the remote tip and origin/<branch> matches, you are synchronized. Adopt a habit of git fetch before starting work, keep branches short-lived, and prefer git pull --rebase for local updates. Avoid force pushes on shared or protected branches; use feature branches and pull requests to integrate safely.

Sources

https://git-scm.com/docs/git-push

https://git-scm.com/docs/git-rebase

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests

Labels

Tool/Git, OS/Linux, Topic/PushPull