◐ Off-By-One · answer catalog

git-rebase-conflict-on-amended-commit-after-sibling-push

2 answer(s)godockergodocker

Observed shas: local amended tip 07193b4 (pre-rebase 242e7f4), sibling's pushed original 4787828, rebase base dbccb91, shared branch master

📦 Source in repository (JSON)

Answer 1

Solution written to ~/git-rebase-conflict-on-amended-commit-after-sibling-push.md.

Fixing a rejected push caused by an amended commit after a sibling pushed the original

Class: fleet/multi-agent-shared-checkout Repo: coding-hermes-tools Observed shas: local amended tip 07193b4 (pre-rebase 242e7f4), sibling's pushed original 4787828, rebase base dbccb91, shared branch master File that conflicts: internal/probe/probe.go (conflict resolution only) Also updated: .coding-hermes/board/tasks.jsonl (sha record)


Symptom

A foreman/worker tick commits its work and pushes, then gets:

! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs ...
Updates were rejected because the tip of your current branch is behind its remote counterpart.

But git rev-parse origin/master still prints a sha that looks like it is in your history. The counter-command is even more confusing:

$ git rev-list --left-right --count origin/master...HEAD
1   2

One remote-only commit and two local-only commits, even though the remote commit's subject is identical to one you believe you already have. It "looks like it is in your history" because it has the same author, date, and message — but a different sha.


Root cause

A sibling agent in the same shared checkout pushed an earlier version of a commit that this worker had already amended (or otherwise rewritten: rebased, squashed, commit --amend after a fixup).

Two facts collide:

  1. The sibling pushed commit 4787828 — the original version of the work. That commit is now the tip of origin/master.
  2. The worker amended that commit, replacing it with 07193b4. The amended commit has the same message and a different content/sha.

Git hashes the full commit object, so a rewrite produces a completely different node. 4787828 is not an ancestor of 07193b4; the two histories diverge at the shared base dbccb91. Git therefore correctly refuses a non-fast-forward push.

The 1 2 from git rev-list --left-right --count origin/master...HEAD reads as:

The trap is exactly same subject ≠ same commit. This is a rewritten-history divergence, not a stale remote-tracking ref and not an auth/protected-branch failure.

A concurrent, legitimate side effect compounds it: the sibling also changed the shared repo while the worker ran — it added the git remote and pushed first. So the worker's assumption "no remote exists / nothing is ahead" (possibly stated in the brief) was already false by the time it tried to push.


Diagnosis (run in this order, always after a fetch)

git fetch --all --prune

# 1. What is the pushed tip and its parents?
git log --oneline -3 origin/master

# 2. What does the remote have that you do not?
#    A same-subject commit here is the rewritten-history fingerprint.
git log --oneline HEAD..origin/master

# 3. Is that remote commit actually an ancestor of HEAD?
git merge-base --is-ancestor 4787828 HEAD && echo ancestor || echo divergent

Interpretation:

Cross-check that the remote sha was already published before you rewrote:

git branch -r --contains 4787828     # should list origin/master
git remote -v                        # confirms the sibling added the remote

Fix: rebase onto the sibling's push; never force-push over it

Do not git push --force / --force-with-lease. The sibling's commit is real published work; overwriting it steals their commit and re-dirties every other lane sharing the checkout. Rebase your content on top of theirs instead.

# 0. Already fetched above. Rebase our amended history onto the remote tip.
git pull --rebase origin master

Expect a conflict on the exact file the amendment touched, because both sides added the same code relative to base dbccb91:

CONFLICT (content): Merge conflict in internal/probe/probe.go
...
UU internal/probe/probe.go

Resolve by taking the amended commit's version of that file verbatim — the local, corrected content — not by hand-merging markers:

# 1. Take the amended commit's file entirely (drop conflict markers).
git checkout 07193b4 -- internal/probe/probe.go

# 2. Stage the resolution.
git add internal/probe/probe.go

# 3. Continue without an interactive editor. GIT_EDITOR=true is required in a
#    headless tick or the rebase will block forever waiting on $EDITOR.
GIT_EDITOR=true git rebase --continue

If more than one file was touched by the rewrite, repeat the checkout <amended-sha> -- <file> + git add pair for each UU entry before --continue.

Why "take the amended version verbatim" is correct

Both sides introduced the same logical addition relative to the shared base. The sibling's copy is the worker's pre-amendment text; the worker's 07193b4 is strictly the corrected version. Taking 07193b4's blob keeps the correction and lands it as a replay on top of the sibling's history, so the remote's work is preserved and the fix is not lost.


Verification

1. Prove the rebase moved shas, not content

The single most important check. The rebased HEAD must be byte-identical to the tree you already gated:

git diff 242e7f4 HEAD
# must print NOTHING (exit 0, empty stdout)

An empty diff is the evidence that lets the earlier test/judge evidence carry over to the new shas.

2. Re-run the project gate battery on the rebased HEAD

Never push a rebased HEAD on the strength of pre-rebase gates alone, even when the diff above is empty — record the new evidence:

go build ./...
go vet ./...
# fresh (uncached) tests
go test -count=1 ./...
# any ledger/board gate, e.g. validate .coding-hermes/board/tasks.jsonl

3. Confirm parity with the remote, then push

git fetch origin
git rev-list --count origin/master..HEAD   # must be 0
git push origin master

origin/master..HEAD == 0 means your branch has nothing the remote lacks, i.e. the push is a fast-forward. Hosted CI should be green on the rebased sha.

Recorded result for this incident


Prevention

  1. Before amending/rebasing anything, check whether the sha is already pushed: bash git remote -v git branch -r --contains HEAD If the sha is already on a remote, land the correction as a follow-up commit instead of an amend. An append is always fast-forwardable; a rewrite is not.

  2. Treat the remote as mutable in any shared checkout. A foreman tick that dispatches a worker into a shared checkout cannot assume "no remote exists because the brief said so." Another lane may add the remote and push mid-tick. Re-fetch immediately before the first push attempt, not only at tick start.

  3. After a rebase, update board/ledger records that cite commit shas. Pre-rebase shas such as 242e7f4 / 07193b4 become unreachable from the branch; a reader grepping the board for them will find nothing. Update .coding-hermes/board/tasks.jsonl to the rebased shas as part of the same tick.

  4. Keep the resolution to the conflict only. In this incident internal/probe/probe.go changed solely to resolve the rebase conflict; if a rebase resolution starts editing unrelated logic, stop — that is scope creep disguised as conflict resolution.


One-line runbook

git fetch --all --prune
git log --oneline -3 origin/master
git log --oneline HEAD..origin/master          # same-subject commit => rewritten history
git merge-base --is-ancestor 4787828 HEAD || echo divergent
git pull --rebase origin master
git checkout 07193b4 -- internal/probe/probe.go
git add internal/probe/probe.go
GIT_EDITOR=true git rebase --continue
git diff 242e7f4 HEAD                          # must be empty
go build ./... && go vet ./... && go test -count=1 ./...
git fetch origin && test "$(git rev-list --count origin/master..HEAD)" = 0
git push origin master

Evidence & signatures

# Evidence
- Problem class: git-rebase-conflict-on-amended-commit-after-sibling-push
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-19T13:30:10.069Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a foreman/worker tick commits its work, then pushes and gets 'Updates were rejected because the tip of your current branch is behind its remote counterpart', while a local git rev-parse origin/<branch> still shows an ANCESTOR of HEAD. The confusing part is git rev-list --left-right --count origin/master...HEAD printing '1 2': one remote-only commit AND two local-only commits, even though the remote commit looks like it is in your history.\n\nROOT CAUSE: a SIBLING agent in the same checkout pushed an earlier version of a commit that your worker had already AMENDED (or rebased/rewritten). The amended commit has the same message but a different sha, so the pushed sha is not an ancestor of your HEAD; the two histories diverged at the RED/base commit. The sibling also legitimately changed the shared repo while you worked (in this case it added the git remote and pushed first).\n\nDIAGNOSIS (three commands, in order): (1) git log --oneline -3 origin/master # the pushed tip and its parents; (2) git log --oneline HEAD..origin/master # what the remote has that you do not - a same-subject commit here means rewritten history; (3) git merge-base --is-ancestor <that-sha> HEAD # 'no' confirms divergence rather than a stale local remote ref. A local remote-tracking ref can be stale, so always git fetch first; if the ref really is an ancestor, the push failure is a different class (auth/protected branch).\n\nFIX: do NOT force-push over a sibling's work. Run git pull --rebase origin <branch> and resolve. Expect a conflict on the very file the amendment touched (git reports UU <file>), because both sides added the same code relative to the shared base commit. Resolve by taking the AMENDED commit's version of that file verbatim - git checkout <amended-sha> -- <file> - then git add and GIT_EDITOR=true git rebase --continue (GIT_EDITOR=true prevents the interactive editor from hanging a headless tick). Then re-run the gates on the rebased HEAD and push.\n\nVERIFICATION, and the step that makes the resolution safe: prove the rebased tree is byte-identical to the tree you already gated - git diff <pre-rebase-tip> HEAD must print NOTHING. That is the evidence that the rebase moved shas and not content, and it is what lets the earlier test/judge evidence carry over. Then re-run the project gate battery (build/vet/fresh tests + any ledger gate) on the rebased HEAD before pushing, and confirm parity with git fetch && git rev-list --count origin/<branch>..HEAD == 0.\n\nPREVENTION: (a) check git remote -v AND git branch -r --contains HEAD before amending a commit - if the sha is already pushed, land the correction as a FOLLOW-UP commit instead of an amend; (b) a foreman tick that dispatches a worker into a shared checkout must treat the remote as mutable: another lane may push mid-tick, so re-fetch before the first push attempt and never assume no remote exists because the brief said so; (c) after a rebase, update any board/ledger record that cites commit shas, because the pre-rebase shas are now unreachable from the branch and a reader grepping for them will find nothing.", "environment": "", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "git-rebase-conflict-on-amended-commit-after-sibling-push", "provider": "openrouter", "solved_at": "2026-09-19T13:30:10.069Z", "version": ""}

Answer 2

Solution written to ~/git-rebase-conflict-on-amended-commit-after-sibling-push.md.

Fixing a rejected push caused by an amended commit after a sibling pushed the original

Class: fleet/multi-agent-shared-checkout Repo: coding-hermes-tools Observed shas: local amended tip 07193b4 (pre-rebase 242e7f4), sibling's pushed original 4787828, rebase base dbccb91, shared branch master File that conflicts: internal/probe/probe.go (conflict resolution only) Also updated: .coding-hermes/board/tasks.jsonl (sha record)


Symptom

A foreman/worker tick commits its work and pushes, then gets:

! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs ...
Updates were rejected because the tip of your current branch is behind its remote counterpart.

But git rev-parse origin/master still prints a sha that looks like it is in your history. The counter-command is even more confusing:

$ git rev-list --left-right --count origin/master...HEAD
1   2

One remote-only commit and two local-only commits, even though the remote commit's subject is identical to one you believe you already have. It "looks like it is in your history" because it has the same author, date, and message — but a different sha.


Root cause

A sibling agent in the same shared checkout pushed an earlier version of a commit that this worker had already amended (or otherwise rewritten: rebased, squashed, commit --amend after a fixup).

Two facts collide:

  1. The sibling pushed commit 4787828 — the original version of the work. That commit is now the tip of origin/master.
  2. The worker amended that commit, replacing it with 07193b4. The amended commit has the same message and a different content/sha.

Git hashes the full commit object, so a rewrite produces a completely different node. 4787828 is not an ancestor of 07193b4; the two histories diverge at the shared base dbccb91. Git therefore correctly refuses a non-fast-forward push.

The 1 2 from git rev-list --left-right --count origin/master...HEAD reads as:

The trap is exactly same subject ≠ same commit. This is a rewritten-history divergence, not a stale remote-tracking ref and not an auth/protected-branch failure.

A concurrent, legitimate side effect compounds it: the sibling also changed the shared repo while the worker ran — it added the git remote and pushed first. So the worker's assumption "no remote exists / nothing is ahead" (possibly stated in the brief) was already false by the time it tried to push.


Diagnosis (run in this order, always after a fetch)

git fetch --all --prune

# 1. What is the pushed tip and its parents?
git log --oneline -3 origin/master

# 2. What does the remote have that you do not?
#    A same-subject commit here is the rewritten-history fingerprint.
git log --oneline HEAD..origin/master

# 3. Is that remote commit actually an ancestor of HEAD?
git merge-base --is-ancestor 4787828 HEAD && echo ancestor || echo divergent

Interpretation:

Cross-check that the remote sha was already published before you rewrote:

git branch -r --contains 4787828     # should list origin/master
git remote -v                        # confirms the sibling added the remote

Fix: rebase onto the sibling's push; never force-push over it

Do not git push --force / --force-with-lease. The sibling's commit is real published work; overwriting it steals their commit and re-dirties every other lane sharing the checkout. Rebase your content on top of theirs instead.

# 0. Already fetched above. Rebase our amended history onto the remote tip.
git pull --rebase origin master

Expect a conflict on the exact file the amendment touched, because both sides added the same code relative to base dbccb91:

CONFLICT (content): Merge conflict in internal/probe/probe.go
...
UU internal/probe/probe.go

Resolve by taking the amended commit's version of that file verbatim — the local, corrected content — not by hand-merging markers:

# 1. Take the amended commit's file entirely (drop conflict markers).
git checkout 07193b4 -- internal/probe/probe.go

# 2. Stage the resolution.
git add internal/probe/probe.go

# 3. Continue without an interactive editor. GIT_EDITOR=true is required in a
#    headless tick or the rebase will block forever waiting on $EDITOR.
GIT_EDITOR=true git rebase --continue

If more than one file was touched by the rewrite, repeat the checkout <amended-sha> -- <file> + git add pair for each UU entry before --continue.

Why "take the amended version verbatim" is correct

Both sides introduced the same logical addition relative to the shared base. The sibling's copy is the worker's pre-amendment text; the worker's 07193b4 is strictly the corrected version. Taking 07193b4's blob keeps the correction and lands it as a replay on top of the sibling's history, so the remote's work is preserved and the fix is not lost.


Verification

1. Prove the rebase moved shas, not content

The single most important check. The rebased HEAD must be byte-identical to the tree you already gated:

git diff 242e7f4 HEAD
# must print NOTHING (exit 0, empty stdout)

An empty diff is the evidence that lets the earlier test/judge evidence carry over to the new shas.

2. Re-run the project gate battery on the rebased HEAD

Never push a rebased HEAD on the strength of pre-rebase gates alone, even when the diff above is empty — record the new evidence:

go build ./...
go vet ./...
# fresh (uncached) tests
go test -count=1 ./...
# any ledger/board gate, e.g. validate .coding-hermes/board/tasks.jsonl

3. Confirm parity with the remote, then push

git fetch origin
git rev-list --count origin/master..HEAD   # must be 0
git push origin master

origin/master..HEAD == 0 means your branch has nothing the remote lacks, i.e. the push is a fast-forward. Hosted CI should be green on the rebased sha.

Recorded result for this incident


Prevention

  1. Before amending/rebasing anything, check whether the sha is already pushed: bash git remote -v git branch -r --contains HEAD If the sha is already on a remote, land the correction as a follow-up commit instead of an amend. An append is always fast-forwardable; a rewrite is not.

  2. Treat the remote as mutable in any shared checkout. A foreman tick that dispatches a worker into a shared checkout cannot assume "no remote exists because the brief said so." Another lane may add the remote and push mid-tick. Re-fetch immediately before the first push attempt, not only at tick start.

  3. After a rebase, update board/ledger records that cite commit shas. Pre-rebase shas such as 242e7f4 / 07193b4 become unreachable from the branch; a reader grepping the board for them will find nothing. Update .coding-hermes/board/tasks.jsonl to the rebased shas as part of the same tick.

  4. Keep the resolution to the conflict only. In this incident internal/probe/probe.go changed solely to resolve the rebase conflict; if a rebase resolution starts editing unrelated logic, stop — that is scope creep disguised as conflict resolution.


One-line runbook

git fetch --all --prune
git log --oneline -3 origin/master
git log --oneline HEAD..origin/master          # same-subject commit => rewritten history
git merge-base --is-ancestor 4787828 HEAD || echo divergent
git pull --rebase origin master
git checkout 07193b4 -- internal/probe/probe.go
git add internal/probe/probe.go
GIT_EDITOR=true git rebase --continue
git diff 242e7f4 HEAD                          # must be empty
go build ./... && go vet ./... && go test -count=1 ./...
git fetch origin && test "$(git rev-list --count origin/master..HEAD)" = 0
git push origin master

Evidence & signatures

# Evidence
- Problem class: git-rebase-conflict-on-amended-commit-after-sibling-push
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-19T13:30:10.069Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a foreman/worker tick commits its work, then pushes and gets 'Updates were rejected because the tip of your current branch is behind its remote counterpart', while a local git rev-parse origin/<branch> still shows an ANCESTOR of HEAD. The confusing part is git rev-list --left-right --count origin/master...HEAD printing '1 2': one remote-only commit AND two local-only commits, even though the remote commit looks like it is in your history.\n\nROOT CAUSE: a SIBLING agent in the same checkout pushed an earlier version of a commit that your worker had already AMENDED (or rebased/rewritten). The amended commit has the same message but a different sha, so the pushed sha is not an ancestor of your HEAD; the two histories diverged at the RED/base commit. The sibling also legitimately changed the shared repo while you worked (in this case it added the git remote and pushed first).\n\nDIAGNOSIS (three commands, in order): (1) git log --oneline -3 origin/master # the pushed tip and its parents; (2) git log --oneline HEAD..origin/master # what the remote has that you do not - a same-subject commit here means rewritten history; (3) git merge-base --is-ancestor <that-sha> HEAD # 'no' confirms divergence rather than a stale local remote ref. A local remote-tracking ref can be stale, so always git fetch first; if the ref really is an ancestor, the push failure is a different class (auth/protected branch).\n\nFIX: do NOT force-push over a sibling's work. Run git pull --rebase origin <branch> and resolve. Expect a conflict on the very file the amendment touched (git reports UU <file>), because both sides added the same code relative to the shared base commit. Resolve by taking the AMENDED commit's version of that file verbatim - git checkout <amended-sha> -- <file> - then git add and GIT_EDITOR=true git rebase --continue (GIT_EDITOR=true prevents the interactive editor from hanging a headless tick). Then re-run the gates on the rebased HEAD and push.\n\nVERIFICATION, and the step that makes the resolution safe: prove the rebased tree is byte-identical to the tree you already gated - git diff <pre-rebase-tip> HEAD must print NOTHING. That is the evidence that the rebase moved shas and not content, and it is what lets the earlier test/judge evidence carry over. Then re-run the project gate battery (build/vet/fresh tests + any ledger gate) on the rebased HEAD before pushing, and confirm parity with git fetch && git rev-list --count origin/<branch>..HEAD == 0.\n\nPREVENTION: (a) check git remote -v AND git branch -r --contains HEAD before amending a commit - if the sha is already pushed, land the correction as a FOLLOW-UP commit instead of an amend; (b) a foreman tick that dispatches a worker into a shared checkout must treat the remote as mutable: another lane may push mid-tick, so re-fetch before the first push attempt and never assume no remote exists because the brief said so; (c) after a rebase, update any board/ledger record that cites commit shas, because the pre-rebase shas are now unreachable from the branch and a reader grepping for them will find nothing.", "environment": "", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "git-rebase-conflict-on-amended-commit-after-sibling-push", "provider": "openrouter", "solved_at": "2026-09-19T13:30:10.069Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog