Advanced Submit Strategies¶
Submitting is more than just pushing branches. This guide covers partial submits, reviewer assignment, PR templates, draft PRs, and strategies for managing complex submission scenarios.
Partial Submits¶
By default, gt submit pushes all unsubmitted branches in your current stack. Sometimes you only want to submit a subset.
Submitting a Range¶
# Submit from a specific branch to the top of the stack
gt submit --from feature/auth-models
# Submit up to a specific branch
gt submit --to feature/auth-api
# Submit only a single branch
gt submit --only feature/auth-models
Use Cases¶
Submit bottom PRs first:
# You have a 5-branch stack. The bottom 2 are ready for review,
# the top 3 are still WIP.
gt submit --to feature/auth-api
# Only submits feature/auth-models and feature/auth-api
Submit a middle branch:
# You want feedback on a specific branch without submitting everything above it
gt submit --only feature/auth-api
Submit current branch and descendants:
# You're on feature/auth-ui, submit it and everything below that isn't submitted
gt submit --from feature/auth-ui
Reviewer Assignment¶
Assigning reviewers at submit time saves a step.
Assign Individual Reviewers¶
# Assign reviewers when submitting
gt submit --reviewers alice,bob
# Per-branch reviewers (via config)
gt config submit.default-reviewers "alice,bob,charlie"
Code Owners Integration¶
Stack respects .github/CODEOWNERS and .gitlab/CODEOWNERS:
# If CODEOWNERS assigns @frontend to src/ui/, Stack will
# suggest or auto-assign those reviewers when submitting
# branches that touch those files.
gt submit --auto-reviewers
Reviewer Rotation¶
For teams with round-robin review:
# Configured in .stkd/config.toml
[submit]
reviewer-rotation = ["alice", "bob", "charlie"]
# Stack assigns the next reviewer in rotation
gt submit --rotate-reviewers
Labels and Milestones¶
Organize PRs with labels and milestones at submit time.
Adding Labels¶
# Add labels to all submitted PRs
gt submit --labels "enhancement,needs-review"
# Add different labels per PR
gt submit --label feature/auth-models="foundation" --label feature/auth-api="api"
# Default labels in config
gt config submit.default-labels "stacked-pr"
Milestones¶
# Assign a milestone
gt submit --milestone "Sprint 12"
# Or set a default
gt config submit.default-milestone "Current Sprint"
PR Size Labels¶
Stack can auto-label PRs based on size:
# Config in .stkd/config.toml
[submit]
auto-size-labels = true
# Results in labels:
# - size/XS (< 50 lines)
# - size/S (50-100 lines)
# - size/M (100-250 lines)
# - size/L (250-500 lines)
# - size/XL (> 500 lines)
Draft PRs¶
Submit work-in-progress PRs to get early feedback without signaling they're ready to merge.
Submit as Draft¶
# Submit entire stack as draft
gt submit --draft
# Submit specific branch as draft
gt submit --only feature/auth-api --draft
Convert Draft to Ready¶
# Mark all PRs in stack as ready for review
gt submit --ready
# Mark specific branch as ready
gt submit --only feature/auth-api --ready
When to Use Drafts¶
- Early architecture review: Submit a draft of the data models to get API feedback before building on top of it
- WIP checkpoints: Submit drafts daily so teammates can see progress
- Dependent PRs: Submit the full stack as draft, then mark bottom PRs ready first
# Submit full stack as draft
gt submit --draft
# As each PR gets approved, mark it ready
gt submit --only feature/auth-models --ready
# Reviewers see it's ready and approve
gt land feature/auth-models
gt submit --only feature/auth-api --ready
PR Templates¶
Stack reads PR templates from your repository and pre-fills submission forms.
Template Locations¶
Stack looks for templates in this order:
.github/PULL_REQUEST_TEMPLATE.md(GitHub).github/pull_request_template.md(GitHub, lowercase).gitlab/merge_request_templates/Default.md(GitLab)PULL_REQUEST_TEMPLATE.md(root)
Template Variables¶
Stack replaces these variables in templates:
<!-- .github/PULL_REQUEST_TEMPLATE.md -->
## Summary
{{stack_description}}
## Stack Context
This PR is part of a stack:
{{stack_list}}
## Checklist
- [ ] Tests pass
- [ ] Documentation updated
- [ ] Breaking changes noted
| Variable | Replaced With |
|---|---|
{{stack_description}} |
Auto-generated summary of changes |
{{stack_list}} |
Markdown list of PRs in the stack with links |
{{branch_name}} |
Name of the current branch |
{{parent_branch}} |
Name of the parent branch |
{{commit_message}} |
First line of the commit message |
Stack-Specific Descriptions¶
Stack generates a description for each PR that includes:
# Description
<Auto-generated from commit message>
---
## Stack Information
- **Position**: 2 of 4 in stack
- **Parent PR**: #42 (feature/auth-models)
- **Child PR**: #44 (feature/auth-ui)
## Stack
- #42 `feature/auth-models` ← parent
- #43 `feature/auth-api` ← **this PR**
- #44 `feature/auth-ui` ← child
Updating Existing PRs¶
After modifying a branch, resubmit to update the PR without changing its scope.
Amending a Submitted Branch¶
# You're on feature/auth-api
git add .
gt modify # Amends the branch
gt submit # Updates PR #43 in place
The PR title, description, reviewers, and labels are preserved. Only the diff changes.
Changing PR Metadata¶
# Update reviewers on existing PRs
gt submit --reviewers alice --update-only
# Add labels to existing PRs
gt submit --labels "urgent" --update-only
# Change milestone
gt submit --milestone "Sprint 13" --update-only
Submit Order and Base Branches¶
Understanding how Stack manages base branches during submit helps avoid surprises.
How Base Branches Are Set¶
When you submit:
main
└── feature/a # PR #1, base: main
└── feature/b # PR #2, base: feature/a
└── feature/c # PR #3, base: feature/b
Stack creates:
- PR #1 targeting main
- PR #2 targeting feature/a
- PR #3 targeting feature/b
After Landing a Parent¶
# Land PR #1
gt land feature/a
# Stack automatically updates PR #2's base to main
gt sync
gt submit # PR #2 now targets main
Manual Base Branch Override¶
If you need a branch to target something other than its parent:
# Temporarily change base for submit
gt submit --base main --only feature/b
# Or change permanently
gt track feature/b --parent main
gt restack
gt submit
CI/CD Considerations¶
Triggering CI on Stacked PRs¶
Stacked PRs trigger CI the same way as regular PRs. However, there are nuances:
GitHub Actions example:
name: CI
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Important: fetch the base branch for stacked PRs
fetch-depth: 0
- name: Run tests
run: cargo test
The fetch-depth: 0 is important because stacked PRs may have a base branch that isn't main.
Required Status Checks¶
If your repository requires status checks to pass before merging:
- Each PR in the stack runs CI independently
- Parent PRs must land before child PRs can merge (GitHub enforces this via base branch)
- Use
gt landto merge in order, or enable auto-merge on each PR
Tips for Effective Submits¶
- Submit early, submit often: Get PRs open before they're perfect
- Use drafts for WIP: Don't mark PRs ready until they're actually ready
- Assign reviewers immediately: Saves the "who should review this?" step
- Label by size: Helps reviewers prioritize small PRs
- Write clear commit messages: They become PR descriptions
- Check the stack description: Review what Stack generated before submitting
- Submit from bottom up: The bottom PRs are typically ready first
- Use
--dry-runto preview: See what Stack would do without doing it
Troubleshooting Submits¶
"Base branch does not exist"¶
This happens when the parent branch hasn't been pushed to remote:
"PR already exists for this branch"¶
Stack detects existing PRs and updates them instead of creating duplicates. If it fails:
"Cannot submit, stack has conflicts"¶
Restack first, then submit: