Handling a Rejected git push
1. What is it?
Your git push can be rejected when the remote branch contains commits that your local branch does not have.
This commonly happens when another developer has already pushed changes to the same branch.
For example:
Remote main:
A --- B --- C
Local main:
A --- B --- D
C= another developer's commit already on remoteD= your local commit- Your local branch does not contain
C
If you run:
git push origin main
Git may reject it with a message similar to:
! [rejected] main -> main (non-fast-forward)
Git does this to prevent you from accidentally overwriting or losing remote changes.
2. Simple Syntax / Sample
A safe approach is:
git fetch origin
git status
git pull --rebase origin main
git push origin main
Alternatively, if your team uses merge-based pulls:
git pull origin main
git push origin main
Recommended practical flow
git fetch origin
git log --oneline --graph --all
git pull --rebase origin main
git push origin main
If there are conflicts during the rebase:
# Fix the conflicting files
git add .
git rebase --continue
# After rebase completes
git push origin main
3. Detailed Explanation
Suppose the remote originally contained:
A --- B
You pulled the code and started working.
Meanwhile, another developer pushed commit C:
Remote:
A --- B --- C
You created your own commit D without having C:
Local:
A --- B --- D
Now you execute:
git push origin main
Git cannot simply move the remote branch from C to D, because doing so would discard the history containing C.
Therefore, Git rejects the push.
Step 1: Fetch the latest remote changes
git fetch origin
This downloads the latest remote commits without modifying your working branch.
You can inspect the situation:
git status
or:
git log --oneline --graph --all
You may see:
C origin/main
/
A---B
\
D main
Your local and remote branches have diverged.
Step 2: Integrate the remote changes
There are two common approaches.
Option 1 — Rebase
git pull --rebase origin main
Conceptually, Git:
- Temporarily removes your local commit
D. - Brings your branch up to remote commit
C. - Replays your commit
Don top ofC.
Before:
C
/
A---B
\
D
After rebase:
A --- B --- C --- D'
D' represents the rebased version of your commit.
Now:
git push origin main
The push can proceed as a normal fast-forward update.
This produces a clean, linear history.
Option 2 — Merge
You can instead use:
git pull origin main
Depending on your Git configuration, this can fetch the remote changes and merge them into your local branch.
The resulting history can look like:
C -------
/ \
A---B M
\ /
D -------
M is the merge commit.
Then:
git push origin main
Both approaches preserve the remote developer's changes; the difference is how the histories are combined.
If there is a conflict
For example:
git pull --rebase origin main
Git might report a conflict because you and another developer modified the same part of a file.
Check:
git status
Open and resolve the conflicting file, then:
git add <file>
git rebase --continue
For example:
git add LoginService.cs
git rebase --continue
Continue until the rebase finishes.
Then:
git push origin main
4. Merge vs Rebase
| Merge | Rebase |
|---|---|
| Combines two histories | Replays your commits on top of latest remote commits |
| May create a merge commit | Creates linear history |
| Does not rewrite existing commits | Rewrites the rebased local commits |
| Simple and safe for shared history | Useful for cleaning up local/unshared commits |
| History may contain more branches | History is generally cleaner |
For example:
Merge:
C ------
/ \
A---B M
\ /
D ------
Rebase:
A --- B --- C --- D'
Your team's branching and Git policy should determine which approach you use.
5. What You Should NOT Normally Do
Do not immediately solve the rejection with:
git push --force
A force push can overwrite the remote branch and potentially remove another developer's commits.
For example:
Remote:
A --- B --- C
Local:
A --- B --- D
A careless force push could make the remote history:
A --- B --- D
and commit C would no longer be part of that branch.
If rewriting a remote feature branch is intentionally required, teams often prefer:
git push --force-with-lease
over:
git push --force
--force-with-lease provides an additional safety check, but it still rewrites remote history and should follow your team's policy.
6. Key Points
- A rejected push often means the remote branch has commits your local branch doesn't contain.
- Git rejects a non-fast-forward push to protect remote history.
- First retrieve and inspect the latest changes:
git fetch origin
- Integrate them using your team's preferred strategy:
git pull --rebase origin main
or merge:
git pull origin main
- Resolve conflicts if necessary.
- Then push:
git push origin main
- Don't use
git push --forcemerely to bypass a rejected push. - In normal team development, you will often push a feature branch and create a Pull Request rather than pushing directly to protected
main.
7. Interview Answer
If my
git pushis rejected because the remote branch contains newer commits, I would not force push. I would first fetch the latest remote changes and inspect them. Then I would integrate those changes into my local branch using either merge or rebase according to the team's Git strategy. If there are conflicts, I would resolve them, complete the merge or rebase, test the changes, and then push again. For my own unshared commits,git pull --rebaseis often useful because it keeps the history linear.