Skip to content

Source control: GitHub stack actions, merge and rebase (A6) #642

Closed

Description

@Tryanks

Summary

GitHub native stack actions: merge stack and rebase stack. Phase A6 of #535. Depends on #641. Async merge first, rebase second.

Merge stack

Re-read the stack (GET repos/O/R/stacks?pull_request=N, then the stack detail) to revalidate the stack number and the affected set; reject a changed or missing expected head, a non-open target, drafts. PUT repos/O/R/pulls/N/merge-async with merge method, merge_action: default, the target's head SHA. Poll GET …/merge-async/{uuid} at 1, 2, 4, 8, 10 s then 10 s to a 5-minute deadline; keep the UUID across reconnect; pending at the deadline is an explicit ambiguous result and is never resubmitted; a 409 with an existing UUID is reconciled, not retried; failed is a rejection; merged or enqueued is success (enqueued is not "merged" and does not auto-settle). The stack UI: a stack map in the PR page's layer selector and the linked rows (every layer with its state; the merge scope is the selected layer plus every unmerged layer below it, which land together; drafts and non-open layers below are the blockers, as upstream); merge and rebase actions are offered only from a linked layer's page (a dismissed or not-linked layer shows the map with the actions disabled and the reason); the bottom layer also merges through the async stack merge; a running or unconfirmed operation is host-published state shown on every device, with the operation id in its popover; an unconfirmed merge is kept until a sync observes the result or 24 h pass; rebase has no cancel and never becomes the primary action; the host checks its Git name and email before a rebase; the stack note in the map collapses per device.

Rebase stack

Check every open layer's write permission (viewerPermission ADMIN/MAINTAIN/WRITE or maintainerCanModify) before any mutation. Scratch clone in a temp dir with the token only in a Git extra-header environment (never argv, config or URL), fetch base and layer branches, bottom old parent = merge-base(base, reviewed head), higher old parents = reviewed prior heads; rebase --onto new old per layer from a detached reviewed SHA; push each changed head with --force-with-lease=refs/heads/B:reviewedSha; 120 s per git command; stop at the first conflict, abort the scratch rebase, report the failing PR and the completed lower layers (earlier pushes remain). Does not touch the project checkout. No copied committer identity; equivalence to GitHub's server rebase (signing, approval retention) is not promised without live evidence.

Evidence required

A disposable native stack: queued vs merged; pending, deadline and reconnect; a rebase failing at layer two with a changed-head lease; completed layers reported, no automatic resubmission. Real bare-repo tests for the rebase contract (replay only each layer's own commits; lease preserves a concurrent push; conflict leaves the failing layer untouched).

Reference

T3 Code: apps/server/src/pullRequest/githubStackActions.ts, githubStackRebase.ts, their tests; GitHub docs on stacked pull requests and merge-async. Design: tmp/design/track-a6-ui.md in the maintainer's checkout.

Activity

  1. added a commit that references this issue on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions