Skip to content

Agent resets HEAD past a commit it already pushed, causing a non-fast-forward push rejection #2802

Description

@richardsolomou

Summary

A single small file edit ended up rejected on push with a confusing non-fast-forward error. The cause was self-inflicted: the agent committed and pushed the change, then reset HEAD back to the base commit — leaving the local branch behind the commit it had just pushed. It then re-committed the same change two more times, resetting after each. The final push failed because local was behind remote.

What happened

  1. The change was committed and pushed to the remote.
  2. HEAD was then reset back to the base commit — so local was now one commit behind the remote it had just pushed to.
  3. The identical change was re-committed and reset to base twice more (three commits total for one edit).
  4. The next push was attempted from a local tip that was behind the remote tip, and was rejected:
 ! [rejected]        <branch> (non-fast-forward)
error: failed to push some refs
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart.

The git reflog showed the loop clearly: commit → reset to base → commit → reset to base → commit → reset to base, with the very first commit being the one that reached the remote.

Why this is a bug

  • The agent reset past a commit it had already pushed. Once a commit is on the remote, moving local HEAD behind it guarantees the next push diverges.
  • One small change was committed three times under three different messages, each undone by a reset — wasted work and confusing history.
  • The user saw a scary push error for what should have been a clean one-commit push.

Expected behavior

  • After a successful push, never reset HEAD to a commit behind what was pushed. If the commit flow involves reset/re-commit, it must fast-forward (or rebase) onto the pushed tip before pushing again.
  • The commit step should be idempotent: one logical change → one commit, not commit → reset → re-commit repeated.

Recovery

The staged working-tree change was byte-identical to the pushed commit, so no real divergence existed. Discarding the local copy and fast-forwarding onto the pushed commit resolved it cleanly:

git restore --staged <file>
git checkout -- <file>
git merge --ff-only origin/<branch>

Environment

  • Model: Opus 4.8
  • Single-file documentation edit on a feature branch

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions