← Back to Articles         
Handling a Rejected git push

Handling a Rejected git push

Published on 03 Oct 2026     5 min read Git & GitHub
Scenario Based Questions

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 remote
  • D = 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:

  1. Temporarily removes your local commit D.
  2. Brings your branch up to remote commit C.
  3. Replays your commit D on top of C.

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 --force merely 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 push is 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 --rebase is often useful because it keeps the history linear.

← Back to Articles