What's Actually Happening
When you try to push and get a "non-fast-forward" rejection, Git is protecting you from losing work. The remote branch has commits that your local branch doesn't have, and a simple push would overwrite them.
The Error You'll See
$ git push origin main
To github.com:user/repo.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:user/repo.git'
hint: Updates were rejected because the tip of your current branch
hint: is behind its remote counterpart. Integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.Why This Happens
- 1.Someone else pushed commits - A teammate pushed to the same branch
- 2.You force pushed from another machine - Your other workstation overwrote history
- 3.Rebase rewritten history - You rebased locally but haven't force pushed yet
- 4.Branch protection rules - Server rejects non-fast-forward pushes
Step 1: Check What's Different
See what commits the remote has that you don't:
```bash # Fetch the latest from remote git fetch origin
# See commits on remote that aren't on your branch git log HEAD..origin/main --oneline ```
Output shows commits you're missing:
a1b2c3d Fix authentication bug by teammate
d4e5f6g Add new feature from PR mergeStep 2: Understand the Options
You have two safe choices:
Option A: Merge - Combines remote commits with yours, preserves history
git pull --merge origin mainCreates a merge commit. History shows both branches.
Option B: Rebase - Replays your commits on top of remote
git pull --rebase origin mainYour commits appear after remote commits. Cleaner history, but rewrites your local commits.
Step 3: Merge Approach (Safer for Beginners)
```bash # Pull and merge remote changes git pull origin main
# If there are conflicts, Git will pause # Resolve conflicts in the files, then: git add resolved-file.txt git commit
# Now push should work git push origin main ```
Step 4: Rebase Approach (Cleaner History)
```bash # Pull and rebase your work on top of remote git pull --rebase origin main
# If conflicts occur during rebase: # Fix the file, then: git add resolved-file.txt git rebase --continue
# After rebase completes: git push origin main ```
Step 5: Handling Merge Conflicts
When pulling shows conflicts:
$ git pull origin main
CONFLICT (content): Merge conflict in src/app.js
Automatic merge failed; fix conflicts and then commit the result.Check which files have conflicts:
git statusLook for files marked "both modified". Open them and find conflict markers:
<<<<<<< HEAD
your local changes
=======
remote changes
>>>>>>> origin/mainEdit to resolve - keep the correct version or combine both:
# After resolving all conflicts
git add .
git commit -m "Merge remote changes and resolve conflicts"
git push origin mainStep 6: When You Know Force Push Is Needed
If you intentionally rewrote history (rebase, amend) and need to force push:
# WARNING: This overwrites remote history
# Only use when you're certain it's safe
git push --force-with-lease origin main--force-with-lease is safer than --force - it verifies the remote state before overwriting.
Step 7: Branch Protection Blocking Push
If the remote has branch protection rules:
$ git push --force origin main
remote: error: GH006: Protected branch update failed for main
remote: error: Cannot force-push to a protected branch- 1.Solution options:
- 2.Create a pull request instead of direct push
- 3.Ask admin to temporarily disable protection
- 4.Push to a different branch and PR
# Create feature branch and PR
git checkout -b feature/my-changes
git push origin feature/my-changes
# Then create PR via GitHub/GitLab UIVerify the Fix
After successfully pushing:
```bash git log --oneline -5
# Check remote state git fetch origin git log origin/main --oneline -5 ```
Both should show your commits.
Prevention Tips
Before starting work, always:
```bash # Pull latest before starting new work git pull origin main
# Or use fetch to check without merging git fetch origin git status ```
This reduces the chance of push conflicts.