Handling Push Rejections
When you try to push but someone else has already pushed new commits to the same branch, Git will reject your push. This is one of the most common situations in collaborative work — and it's easy to resolve.
Why Push Gets Rejected
Git requires that your push is a fast-forward — meaning the remote branch's history is a direct ancestor of your local branch. If the remote has commits you don't have, pushing would overwrite them.
Your local: A --- B --- C (main)
Remote: A --- B --- D (origin/main)
You're trying to push C, but the remote already has D. Git refuses:
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally.
The Fix: Pull Then Push
The standard workflow is simple:
- Pull to get the remote changes
- Resolve conflicts if any
- Push again
git pull origin main
# resolve any conflicts if needed
git push origin main
What Happens During Pull
When you pull, Git merges the remote changes into your branch:
Before pull:
local: A --- B --- C (main)
remote: A --- B --- D (origin/main)
After pull (merge):
local: A --- B --- C --- M (main)
\ /
--- D ---
Now your branch includes both C and D, and the push will succeed.
Pull with Rebase (Cleaner History)
Instead of creating a merge commit, you can rebase your work on top of the remote changes:
git pull --rebase origin main
This replays your commits after the remote's commits:
Before:
local: A --- B --- C (main)
remote: A --- B --- D (origin/main)
After pull --rebase:
local: A --- B --- D --- C' (main)
The result is a clean, linear history with no merge commit.
Try it!
Simulate and resolve a push rejection:
- Check your current state:
git log --oneline - Try pushing (it may fail if the remote is ahead):
git push origin main - If rejected, pull first:
git pull origin main - Check that the merge worked:
git log --oneline --graph - Push again:
git push origin main - Confirm success:
git log --oneline
Avoiding Push Conflicts
- Pull before you start working — Start each session with
git pull - Push often — Smaller, frequent pushes reduce the chance of conflicts
- Communicate — Let teammates know when you're working on shared files
- Use feature branches — Work on separate branches to avoid stepping on each other
Never Force Push (Unless You Know What You're Doing)
You might be tempted to use git push --force. This overwrites the remote history and can destroy your teammates' work. Only use it on branches where you're the sole contributor, and even then, prefer --force-with-lease which checks that the remote hasn't changed since your last fetch.