Skip to content

fix(restack): track parent_revision to prevent false conflicts after squash-merge#20

Merged
dubscode merged 3 commits intomainfrom
fix/parent-tracking
Mar 8, 2026
Merged

fix(restack): track parent_revision to prevent false conflicts after squash-merge#20
dubscode merged 3 commits intomainfrom
fix/parent-tracking

Conversation

@dubscode
Copy link
Copy Markdown
Contributor

@dubscode dubscode commented Mar 8, 2026

Summary

  • Adds parent_revision field to Branch state tracking the parent's tip SHA at fork/rebase time
  • Restack uses stored SHA as oldBase instead of getMergeBase(), which resolves to wrong ancestors after squash-merge reparenting
  • Updates parent_revision across create, restack, sync, submit, and post-merge flows
  • Falls back to getMergeBase() when parent_revision is absent (backward compat for existing stacks)
  • Adds CI test coverage reporting with artifact upload

Test plan

  • E2E test: squash-merge-then-restack produces zero false conflicts
  • Backward compat: restack works when parent_revision absent
  • Normal restack updates parent_revision after rebasing
  • parent_revision preserved during post-merge reparenting
  • All 338 tests pass, typecheck clean, lint clean

dubscode added 2 commits March 7, 2026 16:44
…squash-merge

Add parent_revision field to Branch state that stores the parent's tip
SHA at fork/rebase time. Restack uses this as oldBase instead of
getMergeBase(), which resolves to wrong ancestors after reparenting.

- Add parent_revision to Branch interface and addBranchToStack
- Set parent_revision on create, update after restack/sync/submit
- Preserve parent_revision during post-merge reparenting
- Fall back to getMergeBase when parent_revision absent (backward compat)
- Add e2e test for squash-merge-then-restack scenario
- Add test coverage reporting to CI with artifact upload
Copilot AI review requested due to automatic review settings March 8, 2026 01:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds parent_revision tracking to DubStack branch state so restack can use a stable “old base” SHA (instead of git merge-base) and avoid false conflicts/duplicate commits after squash-merge + reparent workflows. Also introduces Vitest coverage reporting in CI and adds bd (beads) repo integration files.

Changes:

  • Add optional parent_revision field to persisted branch state and propagate it through create/restack/sync/submit flows.
  • Update restack to prefer parent_revision for parentOldTip, with fallback to getMergeBase() for backward compatibility; add tests for squash-merge scenarios and state roundtrips.
  • Add Vitest coverage configuration + CI artifact upload; add bd (beads) configuration/hooks and related ignores/docs.

Reviewed changes

Copilot reviewed 26 out of 30 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vitest.config.ts Enables V8 coverage reporting and configures include/exclude/reporters.
src/lib/state.ts Adds parent_revision to Branch and allows addBranchToStack to store it.
src/lib/state.test.ts Adds roundtrip + addBranchToStack tests for parent_revision.
src/commands/sync.ts Updates sync bookkeeping to write parent_revision during markBranchSynced.
src/commands/sync.test.ts Adds tests covering preservation/update behavior for parent_revision during sync flows.
src/commands/submit.ts Sets parent_revision when recording submit baseline metadata.
src/commands/submit.test.ts Adds test asserting submit sets parent_revision to base SHA.
src/commands/restack.ts Uses parent_revision as parentOldTip and updates it after rebases / continue.
src/commands/restack.test.ts Adds coverage for parent_revision behavior and squash-merge-then-restack regression tests.
src/commands/post-merge.test.ts Adds test asserting reparenting preserves parent_revision.
src/commands/create.ts Captures parent tip SHA and stores it as parent_revision on branch creation.
src/commands/create.test.ts Adds test asserting create sets parent_revision to parent tip.
pnpm-lock.yaml Adds lockfile entries for Vitest coverage provider and transitive deps.
package.json Adds test:coverage script and @vitest/coverage-v8 dev dependency.
CLAUDE.md Adds Claude-specific pointer file.
AGENTS.md Adds bd (beads) issue tracking + “landing the plane” workflow documentation.
.gitignore Ignores coverage output and Dolt/DB artifacts.
.github/workflows/ci.yml Runs pnpm test:coverage and uploads coverage/ artifact.
.claude/settings.json Configures Claude hooks to run bd prime.
.beads/metadata.json Adds beads metadata for Dolt-backed tracking.
.beads/interactions.jsonl Adds beads interactions log file.
.beads/hooks/prepare-commit-msg Adds beads-managed git hook wrapper.
.beads/hooks/pre-push Adds beads-managed git hook wrapper.
.beads/hooks/pre-commit Adds beads-managed git hook wrapper.
.beads/hooks/post-merge Adds beads-managed git hook wrapper.
.beads/hooks/post-checkout Adds beads-managed git hook wrapper.
.beads/dolt-monitor.pid.lock Adds beads runtime lock file.
.beads/config.yaml Adds beads configuration template.
.beads/README.md Adds beads usage documentation for the repo.
.beads/.gitignore Ignores beads/Dolt runtime and local-only artifacts within .beads/.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)

src/commands/restack.ts:175

  • executeRestackSteps mutates state (via updateParentRevision) as branches are successfully rebased, but if a later step conflicts you return without persisting those updates. On --continue, the earlier steps are already marked done so their parent_revision updates will never be written, leaving state stale. Consider writing state after each successful rebase, or at least persisting state before returning { status: 'conflict', ... }.
      await rebaseOnto(parentNewTip, step.parentOldTip, step.branch, cwd);
      step.status = 'done';
      rebased.push(step.branch);
      updateParentRevision(state, step.branch, parentNewTip);
      await writeProgress(progress, cwd);
    } catch (error) {
      if (error instanceof DubError && error.message.includes('Conflict')) {
        step.status = 'conflicted';
        await writeProgress(progress, cwd);
        return { status: 'conflict', rebased, conflictBranch: step.branch };
      }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/commands/sync.ts Outdated
Comment thread src/commands/submit.ts Outdated
Comment thread src/commands/restack.ts
- sync: guard parent_revision update with isAncestor check
- submit: only set parent_revision when null (preserve existing fork-point)
- restack: store parentNewTip in progress file for conflict recovery
@dubscode dubscode merged commit 7dc1b0a into main Mar 8, 2026
3 checks passed
@dubscode dubscode deleted the fix/parent-tracking branch March 8, 2026 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants