Installation • What are Stacked PRs? • Quick Start • Configuration • Commands • Workflows • Contributing
Warning
st was written on a weekend for my own personal use, and may not be entirely stable. You're welcome to use it
in its current state, though don't get mad at me if the tool messes up your local tree. I'll remove this warning once
I feel that it's stable for my own usecase.
git clone https://github.com/mahbd/st && \
cd st && \
cargo install --bin st --path . --force- Rust (1.85 or later, 2024 edition)
- Git (2.0 or later)
- GitHub Personal Access Token with the following scopes:
repo:statusrepo:public_repo- For private repositories: full
reposcope
Stacked PRs (also known as stacked diffs or dependent PRs) are a workflow where you break down large changes into smaller, incremental pull requests that build on top of each other.
Example:
main
└── feature/auth-base (PR #1: Add authentication types)
└── feature/auth-api (PR #2: Add authentication API)
└── feature/auth-ui (PR #3: Add login UI)
Benefits:
- Faster reviews: Smaller PRs are easier to review
- Parallel work: Continue working while waiting for reviews
- Better history: Each PR represents a logical unit of change
- Reduced risk: Smaller changes are less likely to introduce bugs
For more information, visit stacking.dev.
Run st in any git repository to set up your configuration:
cd your-repo
st logOn first run, you'll be prompted to configure your GitHub token and preferences.
# Start from main branch
git checkout main
git pull
# Create first branch in the stack
st create feature/step-1
# Make changes, commit them
git add .
git commit -m "Step 1: Add base functionality"
# Create second branch stacked on first
st create feature/step-2
# Make more changes
git add .
git commit -m "Step 2: Add API endpoints"
# Create third branch
st create feature/step-3
git add .
git commit -m "Step 3: Add UI components"st logOutput:
◯ main
├── ● feature/step-1
│ └── ● feature/step-2
│ └── ● feature/step-3 (current)
st submitThis will:
- Push all branches to GitHub
- Create PRs for each branch (with proper base branches)
- Add navigation comments to each PR
Configuration is stored in ~/.st.toml. You can edit it directly or use st config.
# GitHub personal access token (required)
# Get one at: https://github.com/settings/tokens
github_token = "ghp_xxxxxxxxxxxxxxxxxxxx"
# Editor for commit messages and PR descriptions
# Common options: "vim", "emacs", "nano", "code --wait"
editor = "vim"
# Google Gemini API key for AI-generated PR descriptions (optional)
# Get one at: https://aistudio.google.com/app/apikey
gemini_api_key = "your-gemini-api-key"
# PR Templates (optional)
# Define templates for different types of changes
# When submitting a PR:
# - If you have multiple templates, you'll be prompted to choose one
# - If you have one template, it's used automatically
# - The AI (if configured) will use the template to structure the description
[[pr_templates]]
name = "feature"
content = """
## Summary
Brief description of the feature.
## Changes
- Change 1
- Change 2
## Testing
How was this tested?
## Screenshots (if applicable)
"""
[[pr_templates]]
name = "bugfix"
content = """
## Problem
Description of the bug being fixed.
## Root Cause
What caused the bug?
## Solution
How was it fixed?
## Testing
How was the fix verified?
"""
[[pr_templates]]
name = "refactor"
content = """
## Motivation
Why is this refactor needed?
## Changes
What was refactored?
## Impact
What areas of the codebase are affected?
## Testing
How was this tested?
"""
[[pr_templates]]
name = "docs"
content = """
## Summary
What documentation was added/updated?
## Changes
- Change 1
- Change 2
"""- Go to GitHub Settings > Developer settings > Personal access tokens
- Click "Generate new token (classic)"
- Select scopes:
repo:statuspublic_repo(for public repos)repo(for private repos)
- Copy the token and add it to your config
- Go to Google AI Studio
- Create a new API key
- Add it to your config as
gemini_api_key
| Command | Aliases | Description |
|---|---|---|
st create <name> |
c |
Create a new branch stacked on current |
st submit |
s, ss |
Submit stack to GitHub |
st log |
l, ls |
Show branch tree |
st checkout |
co |
Checkout a tracked branch |
st restack |
r, sr |
Rebase branches after changes |
st sync |
rs, sy |
Sync with remote |
st status |
st, stat |
Show PR status on GitHub |
st delete |
d, del |
Delete a tracked branch |
st track |
tr |
Track an existing branch |
st untrack |
ut |
Untrack a branch |
st trunk |
t |
Manage trunk branches |
st config |
cfg |
Edit configuration |
Creates a new branch and tracks it as a child of the current branch.
# Create a branch stacked on current
st create feature/new-feature
# Short alias
st c feature/new-featurePushes branches and creates/updates PRs on GitHub.
# Submit current stack
st submit
# Force push (like git push --force)
st submit --force
st submit -f
# Submit all tracked branches, not just current stack
st submit --all
st submit -aPR Creation Flow:
- Enter PR title
- Select template (if multiple templates configured)
- AI generates description (if Gemini API key configured)
- Edit description in your editor
- Choose if PR is a draft
- PR is created on GitHub
Displays a tree view of all tracked branches.
st log
st l
st lsExample Output:
◯ main
├── ● feature/auth-base
│ ├── ● feature/auth-api
│ │ └── ● feature/auth-ui (current)
│ └── ● feature/auth-tests
└── ● feature/unrelated-change
Legend:
◯= Trunk branch●= Tracked branch(current)= Your current branch
Interactively checkout a tracked branch.
st checkout
st coYou'll see a list of all tracked branches to choose from.
Rebases all branches in the current stack to ensure they're up-to-date with their parents.
st restack
st rWhen to use:
- After making changes to a parent branch
- After pulling updates from remote
- When
sttells you branches need restacking
Syncs local branches with remote, handling merged/closed PRs.
st sync
st sy
# Discover new branches from GitHub PRs (useful on new machines)
st sync --discover
st sync -dWhat it does:
- Fetches from remote
- Detects merged PRs
- Offers to delete merged branches
- Updates local tracking
With --discover flag:
- Scans GitHub PRs for branches created with
st - Auto-fetches missing branches from remote
- Tracks discovered branches automatically
Shows the status of PRs in your current stack.
st status
st statExample Output:
┌─────────────────────┬────────┬─────────┬───────────┐
│ Branch │ PR # │ Status │ Reviews │
├─────────────────────┼────────┼─────────┼───────────┤
│ feature/auth-base │ #123 │ Open │ Approved │
│ feature/auth-api │ #124 │ Open │ Pending │
│ feature/auth-ui │ #125 │ Draft │ - │
└─────────────────────┴────────┴─────────┴───────────┘
Deletes a tracked branch and re-links its children to its parent.
st delete feature/old-branch
st d feature/old-branchTracks an existing branch on top of the current stack.
# Checkout an untracked branch, then track it
git checkout existing-branch
st trackRemoves a branch from st tracking without deleting it.
st untrack feature/some-branch
st ut feature/some-branchManages trunk (base) branches for multi-trunk support.
# List all trunk branches
st trunk list
st trunk ls
# Switch to a different trunk
st trunk switch dev
st trunk sw dev
# Add a new trunk branch
st trunk add staging
# Remove a trunk branch
st trunk remove staging
st trunk rm stagingMulti-trunk example:
# Trunk: main
◯ main
└── ● feature/for-main
# Trunk: dev
◯ dev
└── ● feature/for-dev
Opens your configuration file in your editor.
st config
st cfg# 1. Start from trunk
git checkout main && git pull
# 2. Create first branch
st create feature/part-1
# ... make changes ...
git add . && git commit -m "Part 1"
# 3. Stack another branch
st create feature/part-2
# ... make changes ...
git add . && git commit -m "Part 2"
# 4. Submit all to GitHub
st submit
# 5. Check status
st statusWhen you need to make changes to a branch that has children:
# 1. Checkout the branch to update
st checkout # Select feature/part-1
# 2. Make your changes
git add . && git commit -m "Fix based on review"
# 3. Restack to update children
st restack
# 4. Submit updates
st submit --forceAfter a PR is merged on GitHub:
# 1. Sync to detect merged PRs
st sync
# 2. Follow prompts to delete merged branches
# 3. Restack remaining branches
st restack
# 4. Submit updates (bases will be updated)
st submitFor projects with multiple base branches (e.g., main and develop):
# Add develop as a trunk
st trunk add develop
# Switch to develop trunk
st trunk switch develop
# Create branches based on develop
st create feature/for-develop
# Switch back to main trunk
st trunk switch main
# Branches are isolated per trunk
st log # Only shows main-based branchesWhen you clone a repo that already has PRs created with st:
# Clone the repo
git clone https://github.com/org/repo
cd repo
# Initialize st (select trunk branch when prompted)
st log
# Discover and track existing branches from GitHub PRs
st sync --discover
# st will:
# - Scan GitHub for PRs created with st
# - Fetch missing branches from remote
# - Automatically track all discovered branches
# View the discovered stack
st logCreate sibling branches for parallel features:
# Start with a base feature
git checkout main
st create feature/base
# Create first child
st create feature/child-a
# Go back to base and create sibling
st checkout # Select feature/base
st create feature/child-b
# Result:
# ◯ main
# └── ● feature/base
# ├── ● feature/child-a
# └── ● feature/child-bAdd these to your shell config for even faster access:
# ~/.bashrc or ~/.zshrc
alias sc="st create"
alias ss="st submit"
alias sl="st log"
alias sr="st restack"
alias sco="st checkout"For VS Code users:
editor = "code --wait"For Neovim users:
editor = "nvim"When force pushing after restack:
st submit -fThis is safe because st only pushes branches it tracks.
Always run st log before st submit to verify your stack looks correct.
Run st restack to update branch bases after changes.
Commit or stash your changes before running st commands:
git stash
st restack
git stash popPush the parent branch first:
git push origin parent-branch-name
st submitThis can happen if branches were manually pushed. Fix with:
st submit # Will update PR bases automatically| Feature | Description |
|---|---|
| Stacked PRs | Create and manage dependent PRs easily |
| Multi-Trunk Support | Work with multiple base branches (main, dev, etc.) |
| AI PR Descriptions | Generate descriptions using Google Gemini |
| PR Templates | Consistent PR formatting with customizable templates |
| Stack Navigation Comments | Auto-generated comments linking related PRs |
| Interactive Branch Selection | Easy checkout with fuzzy finding |
| Automatic Restacking | Keep branches up-to-date with parents |
| PR Status Tracking | View PR status without leaving terminal |
| Branch Auto-Discovery | Automatically discover and track branches from GitHub PRs on new machines |
Contributions are welcome! Feel free to:
- Submit an issue for bugs or feature requests
- Open a PR with your changes
- Improve documentation
Beerware License - If you like this tool and we meet someday, you can buy me a beer!
