Skip to content

gt submit

Push branches to remote and create or update pull requests.

Submit is how you share your work. It creates PRs for each branch in your stack, sets the correct base branches, and adds stack context to PR descriptions.

Usage

gt submit [OPTIONS] [BRANCHES...]

Options

Option Description
--dry-run Show what would happen without making changes
--only <branch> Submit only a specific branch
--from <branch> Submit from this branch to the tip of the stack
--to <branch> Submit from the bottom of the stack to this branch
--stack <name> Submit a specific named stack
--draft Create PRs as drafts
--ready Mark existing draft PRs as ready
--reviewers <users> Comma-separated list of reviewers
--labels <labels> Comma-separated list of labels
--milestone <name> Milestone to assign
--template <name> PR template to use
--no-fetch Skip fetching PR status after submitting
--update-only Update existing PRs without creating new ones
--force Force push even if remote has diverged

Examples

Submit Entire Stack

gt submit

Pushes all branches in the current stack and creates/updates PRs for each.

Preview First

gt submit --dry-run

Output:

Would submit:
  feature/auth-models → main (create PR)
  feature/auth-api → feature/auth-models (create PR)
  feature/auth-ui → feature/auth-api (create PR)

Submit a Single Branch

gt submit --only feature/auth-api

Only submits feature/auth-api. Branches above and below it are untouched.

Submit a Range

# Submit from feature/auth-models to the top
gt submit --from feature/auth-models

# Submit up to feature/auth-api (inclusive)
gt submit --to feature/auth-api

# Submit just the middle branch
gt submit --only feature/auth-api

Submit as Draft

# Submit entire stack as draft
gt submit --draft

# Submit specific branch as draft
gt submit --only feature/auth-api --draft

Draft PRs are visible but signal that they're not ready for final review.

Mark as Ready

# Convert all draft PRs in the stack to ready
gt submit --ready

# Convert a specific branch
gt submit --only feature/auth-api --ready

Assign Reviewers

# Assign reviewers to all submitted PRs
gt submit --reviewers alice,bob

# Per-branch reviewers (via config)
gt config submit.default-reviewers "alice,bob,charlie"

Add Labels

# Add labels to all submitted PRs
gt submit --labels "enhancement,needs-review"

# Auto-size labels (configured in .stkd/config.toml)
# Results in labels like size/M for a 150-line PR

Use a PR Template

# Use a specific template from .github/PULL_REQUEST_TEMPLATE/
gt submit --template "api-changes"

Stack reads templates from: - .github/PULL_REQUEST_TEMPLATE.md - .github/PULL_REQUEST_TEMPLATE/*.md - .gitlab/merge_request_templates/*.md

Update Existing PRs

# Update PR metadata without changing diff
gt submit --update-only --labels "urgent"

# Update reviewers on existing PRs
gt submit --update-only --reviewers charlie

This is useful when you want to change PR metadata (labels, reviewers, milestone) without amending commits.

Submit a Specific Stack

# If you have multiple stacks, submit just one
gt submit --stack feature/auth-models

Behavior

Step-by-Step

1. VALIDATE
   - Check that stack has no conflicts
   - Ensure current branch is tracked by Stack

2. RESTACK (if needed)
   - If parents are out of date, restack first
   - This ensures correct diffs on PRs

3. PUSH
   - For each branch in topological order:
     git push --force-with-lease origin <branch>

4. CREATE / UPDATE PRs
   - For branches without PRs: create new PR
   - For branches with PRs: update existing PR
   - Set correct base branch (parent branch)

5. UPDATE DESCRIPTIONS
   - Add stack visualization to each PR description
   - Include parent/child PR links

6. FETCH STATUS (unless --no-fetch)
   - Query provider for PR numbers, states
   - Update local metadata

PR Descriptions

Stack automatically adds a stack visualization to each PR description:

# 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

This helps reviewers understand where each PR fits in the stack.

Base Branch Management

When you submit:

main
 └── feature/auth-models      PR #1, base: main
      └── feature/auth-api    PR #2, base: feature/auth-models
           └── feature/auth-ui PR #3, base: feature/auth-api

Stack creates: - PR #1 targeting main - PR #2 targeting feature/auth-models - PR #3 targeting feature/auth-api

After Landing a Parent

# Land PR #1
gt land feature/auth-models

# Stack automatically updates PR #2's base to main
gt sync
gt submit  # PR #2 now targets main

Partial Submit Strategies

Submit Bottom-Up

The most common approach — submit lower PRs first since they're typically more stable:

# Submit just the bottom 2 branches
gt submit --to feature/auth-api

# Later, submit the rest
gt submit --from feature/auth-ui

Submit as You Go

Create and submit branches incrementally:

gt create feature/step-1
git add .
gt modify
gt submit --only feature/step-1

# Work on next branch
gt create feature/step-2
# ...
gt submit --only feature/step-2

This gets PRs open for review as early as possible.

Draft Stack, Ready Bottom

# Submit full stack as draft
gt submit --draft

# As each PR gets approved, mark it ready
gt submit --only feature/step-1 --ready
# Wait for approval...
gt land feature/step-1
gt submit --only feature/step-2 --ready

Force Push Safety

Stack uses --force-with-lease for pushes:

git push --force-with-lease origin feature/auth-api

This fails if someone else pushed to the branch since you last fetched. If this happens:

# Fetch their changes first
gt sync

# Resolve if needed, then resubmit
gt submit

Never Use --force

Stack does not support --force for submit (it always uses --force-with-lease). If you need to overwrite remote history, use git push --force manually, but be aware that you may lose others' work.

Tips for Effective Submits

  1. Submit early, submit often: Get PRs open before they're perfect
  2. Use drafts for WIP: Don't mark PRs ready until they're actually ready
  3. Assign reviewers immediately: Saves the "who should review this?" step
  4. Label by size: Helps reviewers prioritize small PRs
  5. Write clear commit messages: They become PR descriptions
  6. Check the stack description: Review what Stack generated before submitting
  7. Submit from bottom up: The bottom PRs are typically ready first
  8. Use --dry-run to preview: See what Stack would do without doing it

Troubleshooting Submits

"Base branch does not exist"

The parent branch hasn't been pushed to remote:

# Push parent first
gt submit --to feature/parent
# Then submit the rest
gt submit

"PR already exists for this branch"

Stack detects existing PRs and updates them. If it fails:

# Force update metadata
gt submit --force

"Cannot submit, stack has conflicts"

Restack first, then submit:

gt restack
gt submit

"Remote branch has diverged"

Someone else pushed to the branch:

# Fetch their changes
gt sync

# Review what changed
git log HEAD..origin/feature/branch --oneline

# If safe, resubmit
gt submit