This Git error occurs when you try to push commits but the remote branch has new commits you don't have locally. Fix it by pulling remote changes first with 'git pull' or 'git pull --rebase', then push again. Force pushing should only be used when you intentionally want to overwrite remote history.
This error is Git's safety mechanism preventing you from accidentally overwriting commits on the remote repository. It means the remote branch (e.g., origin/main) contains commits that your local branch doesn't have. When you push, Git checks if your local branch can be "fast-forwarded" to include all remote commits. If the remote has diverged (someone else pushed, or you rebased/amended locally), Git rejects the push to protect those commits. This is one of the most common Git errors, especially when working in teams or across multiple machines. The hint message itself tells you the solution: "integrate the remote changes (e.g., 'git pull ...') before pushing again." Understanding why this happens is crucial: Git's distributed nature means multiple copies of the repository exist. When copies diverge, Git needs explicit instructions on how to reconcile the differences rather than silently overwriting work.
The safest and most common fix is to pull the remote changes first, then push:
# Fetch and merge remote changes
git pull origin <branch-name>
# Then push your changes
git push origin <branch-name>
# Example with main branch
git pull origin main
git push origin mainDuring the pull, Git will attempt to merge the remote changes with your local changes. If there are conflicts, you'll need to resolve them:
# If conflicts occur during pull:
# 1. Open conflicting files and resolve conflicts
# 2. Stage the resolved files
git add <resolved-files>
# 3. Complete the merge
git commit -m "Merge remote changes"
# 4. Push
git push origin <branch-name>This creates a merge commit combining both sets of changes, preserving all history.
If you prefer a linear history without merge commits, use rebase:
# Fetch remote changes and rebase your commits on top
git pull --rebase origin <branch-name>
# Then push
git push origin <branch-name>Rebasing replays your local commits on top of the remote commits, creating a cleaner, linear history. This is especially useful for feature branches.
Configure rebase as default for pull:
# Set for current repository
git config pull.rebase true
# Set globally for all repositories
git config --global pull.rebase trueIf conflicts occur during rebase:
# Resolve conflicts in the indicated files
# Then continue the rebase
git add <resolved-files>
git rebase --continue
# Or abort if things go wrong
git rebase --abortUse force push only when you deliberately want to overwrite the remote branch. Common scenarios:
- You amended a commit and want to update the remote
- You rebased a feature branch and want to update its remote
- You're the only one working on the branch
# Standard force push (use with caution)
git push --force origin <branch-name>
# Safer: force-with-lease (recommended)
git push --force-with-lease origin <branch-name>Always prefer `--force-with-lease` over `--force`:
--force-with-lease checks that the remote branch hasn't been updated since your last fetch. If someone pushed new commits, the push fails, preventing you from accidentally overwriting their work.
# force-with-lease fails if remote has new commits
git push --force-with-lease origin feature-branch
# error: failed to push some refs (if remote changed)
# After this error, fetch and review:
git fetch origin
git log origin/feature-branch --onelineWarning: Never force push to shared branches (main, develop) without team coordination. This rewrites history and can cause serious problems for collaborators.
Before deciding how to proceed, examine what's different between local and remote:
# Fetch remote changes without merging
git fetch origin
# See commits on remote that you don't have locally
git log HEAD..origin/<branch-name> --oneline
# See commits you have locally that aren't on remote
git log origin/<branch-name>..HEAD --oneline
# See all differences
git log --oneline --left-right HEAD...origin/<branch-name>
# < means local commit, > means remote commit
# Compare the actual code changes
git diff HEAD origin/<branch-name>This helps you understand:
- What commits exist on remote that you're missing
- Whether those commits conflict with your work
- If force pushing would lose important work
Example output:
$ git log --oneline --left-right HEAD...origin/main
< abc1234 Your local commit
< def5678 Another local commit
> 111aaaa Remote commit from teammate
> 222bbbb Another remote commitIf you amended a commit that was already pushed, you have two options:
Option 1: Force push (if working alone on the branch)
# After amending
git commit --amend -m "Updated commit message"
# Force push the amended commit
git push --force-with-lease origin <branch-name>Option 2: Create a new commit instead (safer for shared branches)
# Undo the amend
git reset --soft HEAD@{1}
# Create a new separate commit with the changes
git commit -m "Additional changes"
# Normal push works now
git push origin <branch-name>Check if the branch is shared before force pushing:
# See who has been pushing to this branch
git log --format='%an' origin/<branch-name> | sort | uniq
# If others have pushed, coordinate with them before force pushingRebasing rewrites commit history, which causes push rejection. After rebasing:
Option 1: Force push (standard for feature branches)
# After rebasing onto main
git checkout feature-branch
git rebase main
# Force push the rebased branch
git push --force-with-lease origin feature-branchOption 2: If others are working on the same branch
Coordinate with your team. They'll need to update their local copies:
# After someone force pushes a rebased branch
git fetch origin
git checkout feature-branch
git reset --hard origin/feature-branch
# Or if they have local commits to preserve:
git fetch origin
git rebase origin/feature-branchBest practice for pull requests:
- Rebase and force push before the PR is approved
- After approval, use merge or squash-merge to avoid force pushing
- Configure your CI to handle force pushes on feature branches
If you frequently work with remote branches, set up tracking to simplify commands:
# Set upstream when pushing a new branch
git push -u origin <branch-name>
# or
git push --set-upstream origin <branch-name>
# After this, you can use shorter commands:
git pull # instead of git pull origin <branch-name>
git push # instead of git push origin <branch-name>Check current tracking configuration:
# See what branch you're tracking
git branch -vv
# Output shows tracking info in brackets:
# * main abc1234 [origin/main] Latest commit message
# feature def5678 [origin/feature: ahead 2, behind 1] Feature work"ahead 2, behind 1" means:
- You have 2 commits not on remote
- Remote has 1 commit you don't have locally
- You need to pull before pushing
### Understanding Fast-Forward vs Non-Fast-Forward
Git push works by default in "fast-forward" mode. A fast-forward is possible when:
- Your local branch contains all commits from the remote branch
- Your local commits simply extend the remote branch
Remote: A---B---C
Local: A---B---C---D---E (fast-forward possible)
Remote: A---B---C---F (someone else pushed F)
Local: A---B---C---D---E (not fast-forward, push rejected)### Pull Strategies: Merge vs Rebase vs Fast-Forward Only
Configure your preferred strategy:
# Merge (default) - creates merge commits
git config pull.rebase false
# Rebase - replay your commits on top
git config pull.rebase true
# Fast-forward only - fail if not possible
git config pull.ff only### force-with-lease Explained
--force-with-lease is safer than --force because it:
1. Checks your local ref of the remote branch
2. Compares with actual remote ref
3. Only pushes if they match
# Scenario: You fetch, someone pushes, you force push
git fetch origin
# At this point, origin/main = abc123
# Someone else pushes to main
# Now remote main = def456, but your origin/main still = abc123
git push --force-with-lease origin main
# Fails! Your local view of remote is stale
git push --force origin main
# Succeeds but OVERWRITES the other person's work!### Recovering After Accidental Force Push
If you or someone force pushed and lost commits:
# Find the lost commits in reflog (if you had them locally)
git reflog
# Look for the commit before the force push
# Example: HEAD@{2}: commit: Important work
# Create a branch from the lost commit
git branch recovery HEAD@{2}
# Or on the remote, check if GitHub/GitLab kept the old refs
# Look in the repository events/audit log### Protected Branches and Force Push
GitHub/GitLab can protect branches from force pushes:
GitHub:
- Settings > Branches > Branch protection rules
- Enable "Require linear history" to prevent merge commits
- Disable "Allow force pushes" to prevent history rewriting
GitLab:
- Settings > Repository > Protected branches
- "Allowed to force push" setting controls this
### Working Across Multiple Machines
When working on the same branch from different machines:
# Always start your session with:
git fetch origin
git status
# This shows if you're behind/ahead of remote
# Pull before making changes
# At end of session, always push your work:
git push origin <branch-name>### Team Workflows to Minimize This Error
1. Feature branches: Each developer works on their own branch, only they push to it
2. Rebase before merge: Rebase feature branch onto main before merging
3. Squash merges: Combine all feature commits into one on merge
4. Short-lived branches: Merge frequently to reduce divergence
5. Communication: Let team know before force pushing shared branches
### Git Aliases for Common Operations
# Add these to ~/.gitconfig
[alias]
# Pull with rebase
pr = pull --rebase
# Force push with lease (safer)
fpush = push --force-with-lease
# Show divergence from remote
diverge = log --oneline --left-right HEAD...@{u}
# Fetch and show status
sync = !git fetch origin && git statuswarning: BOM detected in file, this may cause issues
UTF-8 Byte Order Mark (BOM) detected in file
fatal: Server does not support --shallow-exclude
Server does not support --shallow-exclude
warning: filtering out blobs larger than limit
Git partial clone filtering large blobs warning
fatal: Server does not support --shallow-since
Server does not support --shallow-since in Git
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server