Skip to content

Add experimental wt step promote command#789

Open
max-sixty wants to merge 15 commits intomainfrom
promote
Open

Add experimental wt step promote command#789
max-sixty wants to merge 15 commits intomainfrom
promote

Conversation

@max-sixty
Copy link
Owner

@max-sixty max-sixty commented Jan 22, 2026

Summary

Adds wt step promote — an experimental command to exchange branches between the main worktree and another worktree. This addresses #738 where users want to move a branch from a worktree into the main worktree.

This is useful when the main worktree has special significance (Docker Compose configs, IDE settings, heavy build artifacts anchored to project root) and hooks aren't yet set up to run on arbitrary worktrees.

Key features:

  • Exchange branches between main worktree and any other worktree
  • Auto-restore: wt step promote from main worktree (no args) restores default branch
  • Shows mismatch state in wt list with ⚑ indicator
  • Warns when creating mismatch, with hint to restore

Example:

# from ~/project (main worktree)
$ wt step promote feature

Before:

  Branch   Path
@ main     ~/project
+ feature  ~/project.feature

After:

  Branch   Path
@ feature  ~/project
+ main     ~/project.feature

To restore: wt step promote main from anywhere, or just wt step promote from the main worktree.

Why experimental

The idiomatic Worktrunk workflow doesn't use promote — instead each worktree has a full environment. This command exists as a transitional tool while migrating to that model.

Test plan

  • New test suite in tests/integration_tests/step_promote.rs
  • Tests for: branch exchange, restore, auto-restore, dirty worktree errors, mismatch indicator in list
  • All 923 tests pass

Closes #738


This was written by Claude Code on behalf of @max-sixty

@max-sixty max-sixty added the feedback-requested Looking for user feedback on this feature label Jan 22, 2026
max-sixty and others added 3 commits January 21, 2026 21:17
- Add auto-restore: running `wt step promote` from main worktree with no args
  restores the default branch (instead of erroring)
- Improve help text with clearer examples showing paths and wt list-style output
- Reduce output verbosity: single success line instead of progress + success + info
- Fix message: "Restoring main worktree" instead of "Restoring canonical worktree state"

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
max-sixty and others added 6 commits January 21, 2026 21:38
Use WorkingTree.run_command() instead - it already runs commands
in the worktree's path.

Co-Authored-By: Claude <noreply@anthropic.com>
- test_promote_bare_repo_no_worktrees: covers empty worktrees check
- test_promote_bare_repo_with_worktrees: covers is_bare() check
- test_promote_detached_head_main: covers DetachedHead error for main worktree

Co-Authored-By: Claude <noreply@anthropic.com>
Covers the DetachedHead error path when running `wt step promote`
without arguments from a linked worktree that has a detached HEAD.

Co-Authored-By: Claude <noreply@anthropic.com>
- Make default_branch() lookup lazy (only when needed for no-arg from main)
- Add rollback on checkout failures to restore worktree state
- Use git switch instead of git checkout for branch changes (safer)
- Use worktree_only_completer() for promote branch argument
- Add exit status assertions to test helpers for better diagnostics

Co-Authored-By: Claude <noreply@anthropic.com>
Remove untestable rollback attempts that added complexity without
being exercisable in tests. The "detach target first" ordering still
protects the main worktree, and error messages provide clear context.

Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts:
#	src/commands/step_commands.rs
max-sixty and others added 5 commits January 22, 2026 01:10
Co-Authored-By: Claude <noreply@anthropic.com>
Resolves merge conflicts by keeping both:
- wt step promote (from promote branch)
- wt step relocate (from main branch)

Updated test expectations for 8 step subcommands.

Co-Authored-By: Claude <noreply@anthropic.com>
Sync generated docs and snapshots after merge.

Co-Authored-By: Claude <noreply@anthropic.com>
@max-sixty
Copy link
Owner Author

Limitation: gitignored files don't move with the branch

The current wt step promote only swaps branches — gitignored/untracked files (target/, node_modules/, .env) stay in their original filesystem locations. A developer who runs expensive builds in a linked worktree loses their build artifacts when promoting.

Why this is tricky:

  • git worktree move doesn't work for the main worktree — Git doesn't support it. This is the same limitation relocate hits; for main worktree relocation, it checks out the default branch and creates a new linked worktree elsewhere (files don't move).

  • Filesystem swap + metadata repair is risky — We could swap directories and fix .git/worktrees/*/gitdir pointers, but the main worktree has an embedded .git/ directory while linked worktrees have a .git file. Lock files, hooks, and index state could get confused. High risk of corruption.

  • Copy-based swap has tradeoffs — Using the copy-ignored infrastructure (reflink where available) avoids touching git metadata, but: not atomic (power failure mid-swap loses files), needs 2x disk space during swap, slow for large directories even with reflink.

  • Accepting the limitation — Document that promote only swaps branches. Simple and safe, but users must manually copy files or rebuild.


This comment was written by Claude Code on behalf of @max-sixty

Resolve conflicts in help snapshot env variables — main added
WORKTRUNK_TEST_POWERSHELL_ENV.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feedback-requested Looking for user feedback on this feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Question: Is there a command to remove a worktree and checkout the branch in main?

1 participant