Skip to content

feat(dx): add worktree:sync mise task to rebase clean worktrees on origin/main - #218

Open
ClintEastman02 wants to merge 7 commits into
aws-samples:mainfrom
ClintEastman02:fix/197-worktree-sync
Open

ClintEastman02 wants to merge 7 commits into
aws-samples:mainfrom
ClintEastman02:fix/197-worktree-sync

Conversation

@ClintEastman02

Copy link
Copy Markdown
Contributor

Summary

Adds a new mise task mise run worktree:sync that fetches origin/main and rebases every clean linked worktree onto it. Implements Option A from #197.

  • Iterates git worktree list --porcelain and rebases each linked worktree
  • Skips dirty worktrees (uncommitted changes) with a SKIP message
  • Skips main/master (rebase isn't the right tool for the primary branch)
  • On rebase conflict, runs git rebase --abort and exits non-zero so the operator surfaces the conflict explicitly rather than leaving a half-rebased state

Also updates AGENTS.md to point contributors at the new task in two places (the worktree common-mistake bullet and the Commands you can use list).

Closes #197

Test plan

Tested locally with four worktree states:

  • Clean worktree behind origin/main → rebased successfully
  • Clean worktree even with origin/main → no-op (rebase reports "up to date")
  • Dirty worktree (uncommitted changes) → SKIP message, not touched
  • Worktree with conflicting commit → FAIL reported, git rebase --abort runs, working tree restored to pre-rebase HEAD, task exits non-zero
  • main worktree → skipped silently
  • TOML parses cleanly (mise tasks --all lists //:worktree:sync)
  • gitleaks clean on the diff

…igin/main

Worktrees branched from origin/main drift silently as other PRs merge,
causing unnecessary conflicts at push time and CI runs against stale
bases. Issue aws-samples#197.

The new `mise run worktree:sync` task fetches origin/main and rebases
every clean linked worktree onto it. Dirty worktrees and main itself
are skipped; conflicting rebases are aborted and reported with a
non-zero exit so the operator can resolve them explicitly rather than
leaving a half-rebased state.

Closes aws-samples#197
@ClintEastman02
ClintEastman02 requested a review from a team as a code owner May 29, 2026 17:58
@scottschreckengaust

Copy link
Copy Markdown
Contributor

Works as designed. I noticed that the script could be enhanced with a "detect already-merged branches" check (e.g., git branch --merged origin/main would catch branches that already merged), but that's a feature enhancement, not a bug. As-is, it correctly reports "I can't rebase this, you need to look at it."

ClintEastman02 and others added 2 commits June 1, 2026 10:13
Address review feedback on PR aws-samples#218: detect worktrees whose HEAD is
already an ancestor of origin/main (i.e. the branch has merged) and
skip them with a MERGED message rather than attempting a no-op rebase.
The operator can then prune the worktree at their leisure.

Suggested by @scottschreckengaust.
@ClintEastman02

Copy link
Copy Markdown
Contributor Author

Good call — added the merged-branch detection in fe30fb7. Worktrees whose HEAD is already an ancestor of origin/main now get reported with a MERGED line and skipped (no-op rebase avoided), so the operator knows the worktree is ready to prune.

Test matrix (all four cases verified locally):

  • Conflicting commit on a stale base → FAIL + git rebase --abort, non-zero exit
  • Branch already merged into origin/mainMERGED, skipped
  • Stale-and-clean (unique commits behind main) → rebased
  • Stale-and-dirty (uncommitted changes) → SKIP
  • main worktree itself → skipped silently

@codecov-commenter

codecov-commenter commented Jun 8, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@1a1b6cc). Learn more about missing BASE report.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #218   +/-   ##
=======================================
  Coverage        ?   86.09%           
=======================================
  Files           ?      167           
  Lines           ?    39535           
  Branches        ?     3923           
=======================================
  Hits            ?    34037           
  Misses          ?     5498           
  Partials        ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@isadeks

isadeks commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Thanks for wiring the rebase automation — the task itself is solid.

Main thing first: this branch is currently conflicting with main and hasn't been updated since June, so it can't merge as-is. Worth a rebase onto origin/main and a conflict resolution pass before we go further — happy to re-review once it's clean.

Two smaller observations on the task while you're in there (neither blocking):

  1. Squash-merged branches aren't detected as merged. git merge-base --is-ancestor HEAD origin/main catches fast-forward / non-squash merges but not squash-merges — after a squash-merge, the branch's HEAD commit is unique to the branch even though its content lives on main. Those worktrees fall through to the rebase path and produce noisy "everything up to date" replays (usually harmless, occasionally duplicates). If aws-samples merges are typically squash, worth an additional check via gh pr list --state merged --head <branch> or an origin/<branch> gone-check.
  2. Add a one-line summary at the end (e.g. rebased: A, merged: B, skipped: C, failed: D) — this task scrolls across N worktrees; a scannable footer beats reading each line.

@scottschreckengaust scottschreckengaust added the v1 Version 1 label Sep 14, 2026

@scottschreckengaust scottschreckengaust left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verdict: Request changes

The worktree:sync task itself is well-built — correct escaping, fail-closed rebase handling, and it parses cleanly (mise tasks --all lists //:worktree:sync). But two blockers stand between it and merge: the backing issue is not approved, and the branch is stale enough that it both conflicts with main and edits an AGENTS.md that no longer exists in its current form.

Vision alignment

Fits well. This is bounded, reviewable developer-experience tooling that reduces base-branch drift (issue #197) — no blast-radius, cost, or control-plane implications. It reinforces the worktree-per-branch workflow the repo already mandates.

Blocking issues

  1. Backing issue #197 is not approved (ADR-003 governance gate). gh issue view 197 shows labels enhancement, tooling, v1 — no approved label. Per ADR-003 and this repo's standing gate, implementation requires an approved issue. This alone precludes an APPROVE verdict. Fix: have a maintainer apply approved to #197 (the issue is well-formed and the PR implements its recommended Option A).

  2. Branch is CONFLICTING and edits a since-rewritten AGENTS.md. mergeable: CONFLICTING; head is from June. Beyond the raw conflict, current main's AGENTS.md has been restructured — the Git worktrees common-mistake bullet and the Commands you can use list this PR patches no longer exist on main (verified: grep 'Git worktrees' AGENTS.md returns nothing). After rebasing, the two worktree:sync references must be re-placed into the new structure (the Worktrees: bullet under Git workflow and the ## Commands (run these) block). A blind rebase will drop or misplace them. (Prior reviewer @isadeks flagged the conflict; it remains true at head.)

Non-blocking suggestions / nits

  1. Squash-merge detection gap (mise.toml:198). git merge-base --is-ancestor HEAD origin/main only catches fast-forward / merge-commit integrations. aws-samples merges recent PRs via squash (history shows ... (#NNN) squashed tips), so a squash-merged branch's HEAD stays unique to the branch and falls through to the rebase path, replaying already-merged content (usually a harmless "up to date" or an empty-commit drop, occasionally a spurious conflict). Consider an origin/<branch>-gone check or gh pr list --state merged --head <branch> as a secondary MERGED signal. (Also raised by @isadeks.)

  2. Add a scannable summary footer. Across N worktrees the per-line output is noisy; a closing rebased: … / merged: … / skipped: … / failed: … line would help. (Also raised by @isadeks.)

  3. TOML string style (mise.toml:180). This is the repo's first """ (basic, escape-processed) multiline run — every other multiline task uses arrays. It forced the \\t double-escaping in the awk/IFS. A ''' literal multiline string would carry the script verbatim (\t, $'\t') with no escaping and less fragility. Correct as written, but literal strings are the safer convention for embedded shell.

  4. Detached-HEAD worktrees are silently skipped (they emit no branch line, so the awk never prints them). Acceptable, but worth a one-line comment so a future reader doesn't think it's a bug.

Documentation

AGENTS.md is updated in two places (good instinct), but against the obsolete pre-rewrite file — see blocker #2. No docs/guides/ or docs/design/ change is required for contributor tooling, so no Starlight mirror regeneration is needed. ROADMAP.md update is not clearly warranted for a dx task. Once rebased, re-verify the two AGENTS.md references land in the current structure.

Tests & CI

No automated test — appropriate, as the repo has no harness for embedded mise shell tasks (and the known shellcheck toolchain gap, #278, means this script isn't linted in CI either). The PR description documents a thorough manual test matrix (clean/behind, even, dirty, conflicting, merged, main). I independently verified bash -n syntax passes and mise parses/lists the task. CI: Validate PR title pass, build (agentcore) pass, auto-approve skipped, Codecov green — but checks ran on a stale base; they must re-run after rebase.

Review agents run

Execution context cannot spawn nested sub-agents, so pr-review-toolkit agents were performed by equivalent hand-analysis (stated per Stage 3):

  • code-reviewer — done by hand (mise.toml shell task + AGENTS.md prose): escaping, set -eu -o pipefail, guard clauses, exit-status propagation reviewed.
  • silent-failure-hunter — done by hand: rebase failure path aborts and sets status=1; --is-ancestor and status --porcelain guarded; rebase --abort || true intentional. No swallowed failures except the documented squash-merge/detached-HEAD skips.
  • comment-analyzer — done by hand: the mise.toml header comment and AGENTS.md bullet accurately describe behavior.
  • pr-test-analyzer — done by hand: no test harness applies (see Tests & CI).
  • type-design-analyzer — omitted: no types (config/prose only).
  • /security-review — omitted: no IAM/Cedar/network/secrets/input-gateway surface. The task runs git rebase locally on clean trees only and aborts on conflict — no privilege or secret exposure.

Human heuristics

  • Proportionality — Pass. A single mise task for a single, well-scoped drift problem; no over-abstraction.
  • Coherence — Concern (mise.toml:180): first """ multiline run in a file that otherwise uses arrays; a ''' literal would match intent better and match the repo's escape-free style.
  • Clarity — Pass. MERGED/SKIP/FAIL prefixes and the header comment make behavior legible.
  • Appropriateness — Concern (mise.toml:198): the merged-detection heuristic isn't verified against this repo's actual squash-merge behavior, so it under-detects real-world merged branches.

Comment thread mise.toml
# If the branch tip is already in origin/main, the work has merged and a
# rebase would either no-op or replay merged commits depending on history.
# Report and skip so the operator can prune the worktree at their leisure.
if git -C "$wt" merge-base --is-ancestor HEAD origin/main 2>/dev/null; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: merge-base --is-ancestor HEAD origin/main misses squash-merged branches. After a squash merge the branch HEAD is still unique to the branch, so it falls through to the rebase path and replays already-merged content. Since this repo squash-merges recent PRs, consider a secondary signal — an origin/<branch>-gone check or gh pr list --state merged --head <branch>.

Comment thread mise.toml
# conflict explicitly rather than silently leaving a half-rebased state.
[tasks."worktree:sync"]
description = "Fetch origin/main and rebase every clean linked worktree onto it"
run = """

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking style: this is the repo's first """ (escape-processed) multiline run, which forced the \\t double-escaping below. A ''' literal multiline string would carry the script verbatim (\t, $'\t') with no escaping and less risk of a future edit mis-escaping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v1 Version 1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(dx): worktree hygiene automation — rebase on main drift

4 participants