Moving Commits Between Branches
sdf move relocates commits from the current branch to its parent in the stack. This is useful when you realize work belongs in a different PR, or when you want to split a large branch into smaller, reviewable pieces.
Basic usage: move to parent
Move commits from the current branch down to its parent:
# You're on feature/api with commits [a1, a2, a3]
# Stack: main ← feature/auth ← feature/api
sdf move a1 a2
This:
- Cherry-picks
a1anda2ontofeature/auth - Rebases
feature/apito strip the moved commits - Cascade-rebases any downstream branches
- Updates the stack state
Constraints:
- Commits must be a contiguous prefix (oldest-first) of the branch
- At least one commit must remain on the source branch
- Working tree must be clean
Splitting a branch into a new branch
When you want to extract commits into a new branch (not the existing parent), combine sdf branch with sdf move:
Pattern: extract work into a new child branch
# Current stack: main ← feature/auth [a1, a2, a3, a4, a5]
# You realize a4 and a5 are a separate concern
# 1. Create a new branch (appended to stack)
sdf branch api-layer
# 2. Switch back to the source branch
sdf switch feature/auth
# 3. Move the newer commits to the new branch
# (move works parent→child direction, so we need a different approach)
This pattern doesn't work directly because sdf move only moves commits down (to the parent). To move commits up (to a child), use git directly:
# 1. Create the new branch at the current tip
sdf branch api-layer
# api-layer now has commits a1-a5 (same as feature/auth)
# 2. Reset feature/auth to drop the commits you want to move
git checkout feature/auth
git reset --hard HEAD~2 # drops a4, a5
# 3. Force-push the trimmed branch
git push --force-with-lease
# 4. Sync to update the stack state
sdf sync
Pattern: split current work into parent PR
This is the primary sdf move use case — you've been working on a branch and realize the first few commits should be their own PR:
# Stack: main ← feature/auth [setup, schema, handlers, tests]
# You want "setup" and "schema" to be a separate PR
# Move commits to the existing parent
sdf move setup schema
# Moves "setup" and "schema" to main (or whatever the parent is)
# feature/auth now only has [handlers, tests]
How it works internally
Before:
parent [p1, p2] ← current [c1, c2, c3] ← downstream [d1]
sdf move c1 c2:
Phase 1: Cherry-pick c1, c2 onto parent
parent [p1, p2, c1, c2]
Phase 2: Rebase current to strip c1, c2
parent [p1, p2, c1, c2] ← current [c3]
Phase 3: Cascade-rebase downstream
parent [p1, p2, c1, c2] ← current [c3] ← downstream [d1]
Phase 4: Save stack state (updated BaseTips)
If conflicts occur during cherry-pick or rebase, Claude is invoked for auto-resolution. If that fails, the operation aborts cleanly and you can resolve manually.
Tips
- Move early, move often. It's easier to move 1-2 commits than to untangle 10.
- Commits must be contiguous. If you need to move non-adjacent commits, use
git rebase -ito reorder them first, thensdf move. - Push after moving.
sdf moveupdates local branches but doesn't push. Runsdf syncafterward to push all changes and update PR bases. - Check with
sdf statusafter moving to verify the stack looks correct.