Skip to content

restack

v0.4.0+

Move a branch to a different parent in the stack. This is useful when you need to reorganize your stack topology—for example, moving a feature branch from one parent to another.

Terminal window
rung restack --onto main
rung restack feature/api --onto main
rung restack --onto feature/base --include-children
rung restack --dry-run
rung restack --force
rung restack --continue
rung restack --abort
  • rung re — shorthand for rung restack
OptionDescription
--onto <branch>New parent branch to rebase onto (required)
--include-childrenAlso rebase all descendant branches
--dry-runShow what would be done without making changes
--forceProceed even if branches have diverged from remote
--continueContinue after resolving conflicts
--abortAbort and restore from backup

When you run rung restack --onto <new-parent>:

  1. Validate — Checks that the move won’t create a cycle in the stack
  2. Backup — Creates backup refs for affected branches
  3. Rebase — Rebases the branch onto the new parent: git rebase --onto <new-parent> <old-parent> <branch>
  4. Update Stack — Updates the stack topology with the new parent relationship
  5. Report — Shows what was restacked

Move a branch to a different parent:

Terminal window
$ rung restack --onto main
Restacked feat-add-api onto main (was: feat-add-model)

To move a branch and all its descendants together:

Terminal window
$ rung restack feat-add-api --onto main --include-children
Restacked feat-add-api onto main
Restacked feat-add-api-tests onto feat-add-api

Preview changes without modifying anything:

Terminal window
$ rung restack --onto main --dry-run
Would restack:
feat-add-api: rebase onto main (currently on feat-add-model)

If a conflict occurs during restack, rung pauses and shows you what to do:

Terminal window
$ rung restack --onto main
Conflict while rebasing feat-add-api
Conflict in: src/api/users.rs
Resolve the conflict, then run:
rung restack --continue
Or abort and restore:
rung restack --abort
  1. Open the conflicting files and resolve the conflicts
  2. Stage the resolved files:
    Terminal window
    git add src/api/users.rs
  3. Continue the restack:
    Terminal window
    rung restack --continue

If you want to discard the partial restack and restore your branches:

Terminal window
rung restack --abort

This restores all affected branches to their pre-restack state using the backup refs.

Rung prevents moves that would create circular dependencies in your stack:

Terminal window
$ rung restack feat-parent --onto feat-child
Error: Cannot restack feat-parent onto feat-child: would create a cycle

A branch cannot be moved onto one of its own descendants.

During a restack operation, rung writes state to .git/rung/restack_state.json:

{
"started_at": "2024-01-15T10:30:00Z",
"backup_id": "1704067200",
"target_branch": "feat-add-api",
"new_parent": "main",
"old_parent": "feat-add-model",
"original_branch": "feat-add-api",
"current_branch": "feat-add-api",
"completed": [],
"remaining": ["feat-add-api-tests"],
"stack_updated": false
}

This allows --continue to resume from where it left off.

If any affected branches have diverged from their remote tracking branches (both local and remote have unique commits), restack will warn and abort:

Terminal window
$ rung restack --onto main
Branch feat-add-api has diverged from remote (2 ahead, 1 behind)
Error: Cannot restack with diverged branches. Use --force to proceed anyway.

Use --force to proceed with diverged branches. This is safe because rung creates backups before any rebase operation.

  • Always commit or stash your changes before restacking
  • The stack topology is updated after all rebases complete successfully
  • Backup refs are stored in .git/rung/backups/ for undo capability
  • Use --include-children when you want to preserve the relative structure of descendant branches
  • Use --force when you intentionally want to restack branches that have diverged from remote
  • sync — Rebase all branches when parents move
  • undo — Restore from last backup
  • status — View stack topology