EMZETT.
Login

Git: push rejected (non-fast-forward)

In short: The server has commits you do not have locally; Git rejects the push until you have fetched and integrated the others’ changes.

In more detail: Message: ! [rejected] main -> main (fetch first) or (non-fast-forward), plus Updates were rejected because the remote contains work that you do not have locally. Git protects against overwriting others’ commits.

In Depth

Causes

  • Someone else (or you from a second device) pushed after your last sync.
  • You changed history locally (rebase, amend, reset) and the branch tip no longer matches the server.
  • Wrong branch or remote.

Solutions

  1. Fetch and integrate: git pull --rebase (linear history) or git pull (merge commit). Resolve conflicts, then git push.
  2. Look first: git fetch and git log HEAD..origin/main show what is new on the server.
  3. After deliberately rewriting history on your own branch: git push --force-with-lease (safer than --force, checks that the server is unchanged).
  4. On shared branches (main, develop) never force; agree or work via pull request.
  5. Wrong branch? git branch -vv shows the upstream.

Mnemonic

--force overwrites blindly and can destroy others’ work. --force-with-lease aborts if the server has meanwhile received new commits. Tell the team beforehand before changing history on shared branches. Protected branches (branch protection) forbid force push altogether in many teams.

See also: Resolving a merge conflict, Git: not a git repository