The Exact Error
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/user/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
Quick summary: The remote branch has commits that your local branch doesn't have. Git refuses to push because it would overwrite those commits. Pull the remote changes, resolve any conflicts, then push again.
Why This Error Happens
1. Someone else pushed to the same branch while you were working on it
2. You pushed from a different machine and the other machine's work is now ahead
3. You reset or rewrote history locally making your branch diverge from the remote
4. You force-pushed previously and are now trying to push normally from an old clone
Step-by-Step Diagnosis
Step 1 ā See how the branches have diverged
git fetch origin
git log --oneline --graph HEAD origin/main
# Shows both branches and where they diverged
Step 2 ā Identify which commits are only on remote
git log HEAD..origin/main --oneline
# These are commits on remote that you don't have locally
Step 3 ā Identify which commits are only local
git log origin/main..HEAD --oneline
# These are your local commits that haven't been pushed yet
Solutions
Solution 1 ā Pull with rebase (recommended for feature branches)
git pull --rebase origin main
# Resolves any conflicts, then:
git push origin main
Rebase replays your commits on top of the remote commits, resulting in a clean linear history.
Solution 2 ā Pull with merge (preserves branch history)
git pull origin main
# Creates a merge commit if there are divergent changes
git push origin main
Solution 3 ā Force push (only for branches you own exclusively)
# Safer force push ā fails if remote was updated since your last fetch
git push --force-with-lease origin feature/my-branch
# Plain force (use with caution):
git push --force origin feature/my-branch
Never force push to main, master, or shared branches.
Solution 4 ā If you pushed to the wrong branch
# Move your commits to a new branch and reset the wrong branch
git branch my-work # save current commits
git reset --hard origin/main # reset to match remote
git checkout my-work # continue on the correct branch
Real-World Examples
Team workflow ā someone else pushed while you were working:
git fetch origin
git rebase origin/main
# Fix any conflicts in each commit
# git add . && git rebase --continue for each
git push origin feature/my-feature
Squash and force push a PR branch:
git rebase -i origin/main # squash commits
git push --force-with-lease origin feature/my-feature
# Safe because this is your own PR branch
Quick Reference ā Push Rejection Solutions
| Situation | Solution |
|---|---|
| Remote has new commits, clean local | git pull --rebase && git push |
| Remote has new commits, local conflicts | git pull --rebase, resolve, git push |
| Own feature branch, want linear history | git push --force-with-lease |
| Shared branch, preserve all history | git pull --merge && git push |
| Accidentally diverged, want remote state | git reset --hard origin/branch |
Prevent This Error in the Future
1. Pull before you start working ā git pull --rebase at the start of each session.
2. Use short-lived feature branches ā the longer a branch lives, the more it diverges.
3. Set rebase as the default pull strategy:
git config --global pull.rebase true
Use ToolNinja to Debug Faster
The Git Command Generator helps you build the right git commands for common scenarios ā branching, merging, rebasing, and force pushing ā with explanations of what each flag does.
š§ Git Command Generator ā toolninja.io/tools/git-command-generator