Performance & Large Repositories¶
Stack is designed to be fast, but large repositories with thousands of branches or millions of files can slow things down. This guide covers configuration and workflow adjustments to keep Stack responsive.
Understanding Stack's Performance Profile¶
Stack spends most of its time in these areas:
| Operation | Bottleneck | Mitigation |
|---|---|---|
gt sync |
Git fetch + rebase | Shallow fetch, prune branches |
gt restack |
Sequential rebases | --current-only, smaller stacks |
gt submit |
Provider API calls | Batch operations, reduce metadata |
gt log |
Loading branch graph | Lazy loading, cache |
| TUI startup | Repository scan | Fast path for common operations |
Shallow Fetch Configuration¶
Fetching full history on every sync is unnecessary for most stacked diff work.
Configure Shallow Fetch¶
# Only fetch recent history
git config --global fetch.depth 50
# Or configure per-repo
git config fetch.depth 50
# Stack respects this setting during gt sync
gt sync
# Fetches only the last 50 commits
Unshallow When Needed¶
If you need full history for a specific operation:
# Temporarily fetch full history
git fetch --unshallow
# Or just fetch a specific deep range
git fetch --depth=500
Pruning Old Branches¶
Branches accumulate over time and slow down Stack's graph operations.
Automatic Pruning¶
Stack removes merged branches during sync:
Manual Cleanup¶
# Delete all merged branches
gt sync --prune
# Or use Git directly to prune remote tracking branches
git fetch --prune origin
# Then sync to clean up Stack metadata
gt sync
Aggressive Cleanup¶
For repositories with hundreds of stale branches:
# List branches not merged to main
gt log --all | grep -E "(merged|closed)"
# Delete specific old branches
gt delete feature/old-branch-1
gt delete feature/old-branch-2
# Bulk delete merged branches older than 30 days
# (Requires scripting against Stack's metadata)
Sync Interval Tuning¶
How often should you sync? It depends on team velocity.
High-Velocity Teams (many merges per hour)¶
# Sync every 30 minutes
gt sync
# Or configure auto-sync in the TUI
# Press 'y' in TUI every so often
Low-Velocity Teams (few merges per day)¶
# Sync once in the morning is usually enough
gt sync
# Sync again before landing
gt sync && gt land feature/x
Avoid Sync Thrashing¶
Don't sync between every command:
# Bad: syncs three times
gt sync && gt create feature/a && gt sync && gt create feature/b && gt sync
# Good: sync once at the start
gt sync
gt create feature/a
gt create feature/b
Working with Monorepos¶
Monorepos (large repositories with many projects) present unique challenges.
Stack Scope¶
Stack operates on the entire repository, not individual projects. In a monorepo:
Your stacks can span multiple directories:
# A stack touching both frontend and backend
gt create feature/auth
git add frontend/src/auth backend/src/auth
gt modify
gt create feature/auth-tests
git add frontend/tests backend/tests
gt modify
Performance Tips for Monorepos¶
- Use sparse checkout if you only work in one directory:
- Avoid
gt log --allin huge repos:
- Split large changes across fewer branches:
In a monorepo, a "small" change might still touch 20 files. That's okay — the key is logical coherence, not line count.
Many Branches Performance¶
Having 50+ active branches can slow down Stack.
Stack Size Limits¶
| Stack Size | Performance | Recommendation |
|---|---|---|
| 1-5 branches | Fast | Ideal |
| 6-10 branches | Slightly slower | Acceptable |
| 11-20 branches | Noticeable lag | Consider landing or splitting |
| 20+ branches | Slow | Break into independent stacks |
Splitting Large Stacks¶
# You have a 15-branch monster stack
gt log
# feature/foundation
# └── feature/api
# └── feature/ui
# └── ... 12 more branches
# Land the bottom half to free up the stack
gt land feature/foundation
gt sync
gt land feature/api
gt sync
# Now the top branches are direct children of main
# and the remaining stack is smaller
Parallel Stacks¶
Instead of one giant stack, use parallel stacks:
# Instead of:
# main → A → B → C → D → E → F (6 branches)
# Do:
# main → A → B (stack 1)
# main → C → D (stack 2)
# main → E → F (stack 3)
gt checkout main
gt create feature/part-1
gt create feature/part-2
gt checkout main
gt create feature/other-1
gt create feature/other-2
Storage Cleanup¶
Stack's metadata is lightweight, but it accumulates over time.
Metadata Location¶
.git/stkd/
├── state.json # Operation state
├── branches/ # Branch metadata (~200 bytes per branch)
│ ├── feature_a.json
│ └── ...
Cleaning Up Stale Metadata¶
# Remove metadata for deleted branches
gt sync --prune
# Or manually clean up
gt log --all
# Identify branches that no longer exist
gt untrack feature/deleted-branch
Repository Size¶
If your .git/ directory is growing:
# Run Git garbage collection
git gc
# Aggressive cleanup (slow)
git gc --aggressive
# Remove unreachable objects
git prune
Provider API Performance¶
Submitting and syncing involve API calls to GitHub/GitLab.
Rate Limiting¶
GitHub limits unauthenticated requests to 60/hour and authenticated to 5,000/hour. Stack batches API calls, but large stacks can still hit limits.
# Check rate limit status
# (Stack shows warnings when approaching limits)
# Use a personal access token with higher limits
gt auth login github --token
Reducing API Calls¶
# Submit without fetching MR status (fewer API calls)
gt submit --no-fetch
# Sync without provider checks
gt sync --no-provider
Caching Provider Data¶
Stack caches MR status locally:
Cache expires after 5 minutes. You can force refresh:
TUI Performance¶
The TUI can become sluggish in large repos.
Startup Optimization¶
The TUI loads the full branch graph on startup. In repos with 100+ branches:
# Use CLI instead for quick operations
gt log # Faster than TUI startup
# Or filter the view
gt log --stack feature/auth
Runtime Optimization¶
In the TUI:
- Press g sparingly (it triggers provider API calls)
- Use j/k navigation instead of loading full stacks
- Exit TUI (q) and use CLI for bulk operations
Benchmarks¶
Expected performance on a typical repository (10,000 commits, 50 branches):
| Command | Time |
|---|---|
gt log |
< 100ms |
gt sync |
1-3s |
gt restack (5 branches) |
2-5s |
gt submit (5 branches) |
3-8s |
| TUI startup | 500ms - 1s |
On very large repos (1M+ commits, 500+ branches):
| Command | Time |
|---|---|
gt log |
500ms - 1s |
gt sync |
5-10s |
gt restack (5 branches) |
5-15s |
gt submit (5 branches) |
5-15s |
| TUI startup | 2-5s |
Performance Checklist¶
- [ ] Configure shallow fetch (
fetch.depth = 50) - [ ] Run
gt sync --pruneweekly - [ ] Keep stacks under 10 branches
- [ ] Use parallel stacks instead of one giant stack
- [ ] Run
git gcmonthly - [ ] Use
gt sync --no-providerwhen you don't need MR status - [ ] Avoid
gt log --allin repos with 100+ branches - [ ] Exit TUI for bulk operations
- [ ] Use sparse checkout in monorepos if applicable
- [ ] Keep Stack updated (performance improvements ship regularly)