stack-push
Pushes all branches in a stack and opens or updates one dependent PR per slice. Use after stack-create to publish the stack or after adding commits to a slice.
What this skill does
# Stack Push
Push all branches in a stack and open (or update) one PR
per slice, with each PR targeting its parent branch as base.
## When to Use
Run `stack-push` after `stack-create` has initialized the
branch topology and at least one commit exists on each
slice branch.
Also run it after adding commits to any slice to update
open PRs.
## Prerequisites
- `stack-create` completed: branches exist with commits
- `gh` CLI authenticated (`gh auth status`)
- Each slice branch has at least one commit beyond its base
## Required Progress Tracking
Create `TodoWrite` items before starting:
1. `stack-push:branches-listed`
2. `stack-push:branches-pushed`
3. `stack-push:prs-opened`
4. `stack-push:stack-summary-posted`
## Step 1: List Stack Branches (`branches-listed`)
Identify all branches in the stack.
By convention they share a `stack/<feature-name>/` prefix:
```bash
STACK=stack/my-feature
BASE=master
git branch --list "${STACK}/*" | sed 's/^[* ]*//'
```
Verify each branch has commits beyond the base:
```bash
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//'); do
count=$(git rev-list --count \
"$(git merge-base ${BASE} ${branch})..${branch}")
echo "${branch}: ${count} commit(s)"
done
```
Any branch showing `0 commits` must have work added before
pushing.
## Step 2: Push Branches (`branches-pushed`)
Push every slice branch to the remote in stack order
(base slice first):
```bash
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//' | sort); do
git push --set-upstream origin "${branch}"
echo "pushed: ${branch}"
done
```
### jj Accelerator (if available)
```bash
jj git push --all
```
## Step 3: Open or Update PRs (`prs-opened`)
Create one PR per slice, targeting its parent branch.
For the first slice the parent is `master`; for subsequent
slices the parent is the previous slice's branch.
```bash
PREV_BASE=master
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//' | sort); do
# Check if a PR already exists for this branch
existing=$(gh pr list \
--head "${branch}" \
--json number \
--jq '.[0].number' 2>/dev/null)
if [ -n "${existing}" ]; then
echo "PR #${existing} already open for ${branch} -- skipping"
else
gh pr create \
--base "${PREV_BASE}" \
--head "${branch}" \
--title "[$(echo ${branch} | sed 's|.*/||')] <title>" \
--body "Part of stack \`${STACK}\`." \
--draft
echo "opened PR for ${branch} (base: ${PREV_BASE})"
fi
PREV_BASE="${branch}"
done
```
Fill in the actual PR titles and bodies before removing
the `--draft` flag.
Run `Skill(sanctum:pr-prep)` on each slice to generate
quality-gated descriptions.
## Step 4: Post Stack Summary (`stack-summary-posted`)
After all PRs are open, post a summary comment on the
first PR (the root of the stack) listing the full chain:
```bash
ROOT_PR=$(gh pr list \
--head "${STACK}/$(git branch --list \
"${STACK}/*" | sed 's/^[* ]*//' | sort | head -1 \
| sed 's|.*/||')" \
--json number --jq '.[0].number')
# Build the stack table
BODY="## Stack\n\n| # | Branch | PR |\n|---|--------|----|\n"
N=1
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//' | sort); do
pr_num=$(gh pr list --head "${branch}" \
--json number --jq '.[0].number')
BODY="${BODY}| ${N} | \`${branch}\` | #${pr_num} |\n"
N=$((N+1))
done
gh pr comment "${ROOT_PR}" --body "$(printf "${BODY}")"
```
## Notes
- Always push in stack order so GitHub sees the parent
branch before the child PR is opened
- Use `--draft` by default; promote slices to ready
individually as they pass review
- After any `git rebase --update-refs` run, re-push with
`git push --force-with-lease` (never `--force`)
- When a base PR merges, run `Skill(sanctum:stack-rebase)`
to cascade the rebase before updating the next PR's base
Related in workflow-automation
do-issue
IncludedImplements GitHub or GitLab issues via parallel subagents with review gates between task batches. Use when resolving multi-step issues end-to-end.
stack-mode
IncludedDetects shared stack membership and iterates a command across all PRs in base-to-tip order. Use when a command supports --stack flag for multi-PR iteration.
stack-rebase
IncludedCascades a rebase through an entire PR stack after a base PR merges or upstream changes. Use when a stack needs to incorporate new base branch commits.
stack-create
IncludedInitializes a stacked branch set from an ordered plan, one branch per slice with parent-child links. Use when a plan has 2+ sequentially dependent changes.