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
- The change was committed and pushed to the remote.
HEAD was then reset back to the base commit — so local was now one commit behind the remote it had just pushed to.
- The identical change was re-committed and reset to base twice more (three commits total for one edit).
- 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
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
HEADback 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
HEADwas then reset back to the base commit — so local was now one commit behind the remote it had just pushed to.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
HEADbehind it guarantees the next push diverges.Expected behavior
HEADto 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.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:
Environment