allod change record: resolve a concurrent push on a default branch #124
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
allod/tools#124
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
When two agents commit in place to the same repo's default branch, the second one's push is rejected as non-fast-forward and recovery is manual. This tracks making
allod change recordresolve that itself — and, first, the criterion for deciding whether it is worth building at all. It is split out of allod/tools#118 so the two concurrency refusals there can land without waiting on it.Part of allod/tools#115.
Primary goals:
-c rebase.autoStash=falseexplicitly, because with autostash enabled git stashes the other agent's uncommitted work, rebases, and unstashes it, which is the one genuinely dangerous path here.git rebase --abortand report the original rejection, leaving the branch, working tree, and local commit exactly as they were.Verified behavior
Measured against a two-clone fixture rather than reasoned about, because the safety of this change rests entirely on what git does when a second agent is active in the same tree:
git pull --rebaserefuses —cannot pull with rebase: You have unstaged changesgit rebase --abortThe first row is the important one: git's own dirty-tree guard is what prevents this from reintroducing the collision class allod/tools#115 exists to close, so it is not a hazard that needs new machinery — but it holds only while
rebase.autoStashis false. This VM setspull.rebase trueand leaves autostash unset, so the property holds today by default and would stop holding silently if that config changed. Hence the explicit-c.Why this is deferred rather than dropped
The failure is already loud:
allodrunsset -euo pipefail, so the rejected push atallod:369exits non-zero on its own. The recovery is already documented inallod/memorygit-workflow.mdas one command,git pull --rebasethen push again. So the whole value of this change is saving one command in one flow, against the cost of a rebase state machine with a forced-config requirement and a conflict-abort path that needs its own tests.Architecture principle 15 puts minimalism first and principle 14 says gates that cannot demonstrate their worth get deleted rather than elaborated. Neither says never — they say show the value first.
Decision criterion
Implement when a rejected push in the in-place default-branch flow is observed to cost real recovery cycles rather than being a rare event an agent handles in one command. That becomes measurable once allod/tools#118's guards land and the in-place flow is the only shared-checkout flow left, since allod/tools#116 moves every branch change into its own worktree. If the rejection turns out to be rare at that point, close this as not planned and keep the documented manual recovery.
Scope
In: the push step of
allod change record(allod:369), and tests covering a rejection that rebases and retries cleanly, a rejection that conflicts and aborts, and a rejection while another agent has uncommitted work in the tree. Out: the moved-checkout and swept-edit refusals, which stay in allod/tools#118; worktree creation policy, which is allod/tools#116.