fix(ab-3238): switch drift integration from merge to rebase - #472
Merged
Conversation
PR #471 shipped AB#3238 with git merge --no-ff origin/<target> as the drift-integration strategy. User feedback: clean linear feature-PR history is preferred over preserving the upstream MG-merge SHA chain; the extra integration merge commit polluted the PR's Commits tab. This change: * Script (integrate-target-drift.ps1): replaces git merge --no-ff with git rebase origin/<target>, replaces git push origin <feature> with git push --force-with-lease=<feature>:<expected-sha> (the expected SHA is captured BEFORE rebase to defeat lease-weakening from background fetches). * Conflict path: replaces git merge --abort (guarded by MERGE_HEAD) with git rebase --abort (guarded by Test-RebaseInProgress, which checks both ebase-merge and ebase-apply dirs via git rev-parse --git-path). * New pre-flight: Test-WorktreeBlocked refuses to proceed if any in-progress merge/rebase/cherry-pick/revert OR uncommitted changes are detected, surfaced as new error_code worktree_dirty. * New envelope fields: strategy: 'rebase', old_head_sha, ew_head_sha. Dropped merge_commit_sha (rebase has no single integration SHA). * Edge case: rebase-no-op (HEAD didn't move despite behind_by>0) exits success without force-push. * Initial-push path: if origin/<feature> doesn't exist yet, falls back to git push --set-upstream (no lease — nothing to overwrite). * error_code value merge_conflict retained for workflow-route compatibility (semantic meaning is still 'drift integration conflicted'); only the operator-instructions in the conflict gate prompt change (rebase + force-with-lease, not merge + plain push). * Workflow YAML: version 2.4.9 -> 2.4.10. Updates agent comment, conflict-gate operator instructions (full rebase/continue/force-push recipe with explicit git rev-parse refs/remotes/origin/<feature> for the lease), failed-gate prompt (documents new worktree_dirty and updated push_failed semantics). * Tests: clean-drift test asserts strategy='rebase', new_head_sha != old_head_sha, and verifies the force-pushed SHA landed on origin/<feature>. Conflict test asserts no rebase-merge or rebase-apply dir remains after abort. New worktree_dirty test. Envelope-contract test updated for new field set. 6/6 pass. Lint (lint-feature-pr.ps1) contract unchanged — routes still check �rror_code == 'merge_conflict', gate names + entry-point invariant preserved. 28/29 lint tests pass (1 pre-existing missing-ado-remediation-route failure unrelated to this change). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR #471 (just merged) shipped AB#3238 using
git merge --no-ff origin/<target>as the drift-integration strategy. Per user feedback, the feature PR's Commits tab should show clean linear history — not an extra integration merge commit sitting on top of the feature work. Switching togit rebase+git push --force-with-lease.Why rebase (vs merge)
main(per cloudvault config), so preserving upstream MG-merge SHAs on the feature branch adds nothing — they're discarded at squash anyway.feature_branch_divergedgate make force-push safe given polyphony's branch model (SDLC run is sole writer of the feature branch).What changed
Script (
integrate-target-drift.ps1):git merge --no-ff→git rebase origin/<target>git push origin <feature>→git push --force-with-lease=refs/heads/<feature>:<expected-sha> origin HEAD:refs/heads/<feature>. The expected SHA is capturedBEFORErebase to defeat lease-weakening from background fetches (rubber-duck Q2).git merge --abort(guarded byMERGE_HEAD) →git rebase --abort(guarded byTest-RebaseInProgress, which checks BOTHrebase-mergeandrebase-applydirs viagit rev-parse --git-path).Test-WorktreeBlockedrejects with new error codeworktree_dirtyif any in-progress merge/rebase/cherry-pick/revert OR uncommitted changes are detected (rubber-duck Q6).git push --set-upstream(no lease — nothing to overwrite).strategy: 'rebase',old_head_sha,new_head_shafields. Droppedmerge_commit_sha(rebase has no single integration SHA).error_codevaluemerge_conflictretainedfor workflow-route + lint contract compatibility. The semantic meaning is "drift integration conflicted"; only the operator-instructions in the conflict-gate prompt change.Workflow (
feature-pr.yaml):version: 2.4.9 → 2.4.10git rev-parse refs/remotes/origin/<feature>for the lease,rebase --continueloop, force-with-lease push.worktree_dirtycause + updatedpush_failed(lease-refused) semantics.Tests (
integrate-target-drift.Tests.ps1):strategy='rebase',new_head_sha != old_head_sha,origin/<feature>HEAD landed onnew_head_sha(force-with-lease verified end-to-end).rebase-mergenorrebase-applydir remains after abort.Worktree dirtycontext.Validation
Invoke-Pester .\.conductor\registry\tests\integrate-target-drift.Tests.ps1→ 6 passed, 0 failed.Invoke-Pester .\.conductor\registry\tests\lint-feature-pr.Tests.ps1→ 28/29 passed. The remaining failure (missing-ado-remediation-route) is pre-existing onmainand unrelated.Rubber-duck adoption
--force-with-lease=refs/heads/<feature>:<expected-sha>+HEAD:refs/heads/<feature>push refspec.Test-Path (git rev-parse --git-path rebase-merge)ORrebase-apply(different rebase modes use different dirs).git fetch origin <target> <feature>pre-step + explicit lease.Closes the user-feedback gap on PR #471.