You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
└── feat/frontend → PR #3 (base: feat/api-endpoints) - top (furthest from trunk)
22
22
```
23
23
24
24
The **bottom** of the stack is the branch closest to the trunk, and the **top** is the branch furthest from the trunk. Each branch inherits from the one below it. Navigation commands (`up`, `down`, `top`, `bottom`) follow this model: `up` moves away from trunk, `down` moves toward it.
1.**Always supply branch names as positional arguments** to `init`, `add`, and `checkout`.
47
-
2.**Always use `--auto` when pushing** to skip PR title prompts.
48
-
3.**Always use `--json` when viewing** to get structured output.
49
-
4.**Use `--remote <name>` when multiple remotes are configured**, or set `remote.pushDefault` in git config.
50
-
5.**Avoid branches shared across multiple stacks.** If a branch belongs to multiple stacks, commands exit with code 6. Check out a non-shared branch first.
51
-
6.**Plan your stack layers by dependency order before writing code.** Foundational changes (models, APIs, shared utilities) go in lower branches; dependent changes (UI, consumers) go in higher branches. Think through the dependency chain before running `gh stack init`.
52
-
7.**Use standard `git add` and `git commit` for staging and committing.** This gives you full control over which changes go into each branch. The `-Am` shortcut is available but should not be the default approach—stacked PRs are most effective when each branch contains a deliberate, logical set of changes.
53
-
8.**Navigate down the stack when you need to change a lower layer.** If you're working on a frontend branch and realize you need API changes, don't hack around it at the current layer. Navigate to the appropriate branch (`gh stack down`, `gh stack checkout`, or `gh stack bottom`), make and commit the changes there, run `gh stack rebase --upstack`, then navigate back up to continue.
47
+
2.**When a prefix is set, pass only the suffix to `add`.**`gh stack add auth` with prefix `feat` → `feat/auth`. Passing `feat/auth` creates `feat/feat/auth`.
48
+
3.**Always use `--auto` when pushing** to skip PR title prompts.
49
+
4.**Always use `--json` when viewing** to get structured output.
50
+
5.**Use `--remote <name>` when multiple remotes are configured**, or set `remote.pushDefault` in git config.
51
+
6.**Avoid branches shared across multiple stacks.** If a branch belongs to multiple stacks, commands exit with code 6. Check out a non-shared branch first.
52
+
7.**Plan your stack layers by dependency order before writing code.** Foundational changes (models, APIs, shared utilities) go in lower branches; dependent changes (UI, consumers) go in higher branches. Think through the dependency chain before running `gh stack init`.
53
+
8.**Use standard `git add` and `git commit` for staging and committing.** This gives you full control over which changes go into each branch. The `-Am` shortcut is available but should not be the default approach—stacked PRs are most effective when each branch contains a deliberate, logical set of changes.
54
+
9.**Navigate down the stack when you need to change a lower layer.** If you're working on a frontend branch and realize you need API changes, don't hack around it at the current layer. Navigate to the appropriate branch (`gh stack down`, `gh stack checkout`, or `gh stack bottom`), make and commit the changes there, run `gh stack rebase --upstack`, then navigate back up to continue.
54
55
55
56
## Thinking about stack structure
56
57
@@ -64,29 +65,38 @@ Stacked branches form a dependency chain: each branch builds on the one below it
64
65
65
66
```
66
67
main (trunk)
67
-
└── data-models ← shared types, database schema
68
-
└── api-endpoints ← API routes that use the models
69
-
└── frontend-ui ← UI components that call the APIs
70
-
└── integration ← tests that exercise the full stack
└── feat/api-endpoints ← API routes that use the models
70
+
└── feat/frontend-ui ← UI components that call the APIs
71
+
└── feat/integration ← tests that exercise the full stack
71
72
```
72
73
73
74
This is illustrative — choose branch names and layer boundaries that reflect the specific work you're doing. The key principle is: if code in one layer depends on code in another, the dependency must be in the same branch or a lower one.
74
75
76
+
### Branch naming
77
+
78
+
Prefer initializing stacks with a prefix (`-p`). Prefixes group branches under a namespace (e.g., `feat/auth`, `feat/api`) and keep branch names clean and consistent. When a prefix is set, pass only the suffix to subsequent `add` calls — the prefix is applied automatically. Without a prefix, you'll need to pass the full branch name each time.
79
+
75
80
### Staging changes deliberately
76
81
77
-
Don't dump all changes into a single commit or branch. Stage changes in batches based on logical grouping:
82
+
The main reason to use `git add` and `git commit` directly is to control **which changes go into which branch**. When you have multiple files in your working tree, you can stage a subset for the current branch, commit them, then create a new branch and stage the rest there:
78
83
79
84
```bash
80
-
# Stage only the model files for this branch
85
+
# You're on feat/data-models with several new files in your working tree.
Multiple commits per branch are fine and encouraged—they make the PR easier to review. The key is that all commits in a branch relate to the same logical concern.
99
+
This keeps each branch focused on one concern. Multiple commits per branch are fine — the key is that all commits in a branch relate to the same logical concern, and changes that belong to a different concern go in a different branch.
90
100
91
101
### When to create a new branch
92
102
@@ -111,12 +121,12 @@ Small, incidental fixes (e.g., fixing a typo you noticed) can go in the current
111
121
112
122
| Task | Command |
113
123
|------|---------|
114
-
| Create a stack |`gh stack init branch-a`|
115
-
| Create a stack with a prefix |`gh stack init -p feat auth`|
# → feat/api-routes and feat/api-tests show updated heads
307
+
# → feat/api-routes and feat/frontend show updated heads
298
308
```
299
309
300
310
If `sync` hits a conflict during this process, it restores all branches to their pre-rebase state and exits with code 3. See [Handle rebase conflicts](#handle-rebase-conflicts-agent-workflow) for the resolution workflow.
# Create a stack with new branches (branched from trunk)
379
+
# Set a branch prefix (recommended — subsequent `add` calls only need the suffix)
380
+
gh stack init -p feat auth
381
+
# → creates feat/auth
382
+
383
+
# Multi-part prefix (slashes are fine — suffix-only rule still applies)
384
+
gh stack init -p monalisa/billing auth
385
+
# → creates monalisa/billing/auth
386
+
387
+
# Create a stack with new branches (no prefix — use full branch names)
370
388
gh stack init branch-a branch-b branch-c
371
389
372
390
# Use a different trunk branch
373
391
gh stack init --base develop branch-a branch-b
374
392
375
393
# Adopt existing branches into a stack
376
394
gh stack init --adopt branch-a branch-b branch-c
377
-
378
-
# Set a branch prefix (branch names you provide are automatically prefixed)
379
-
gh stack init -p feat auth
380
-
# → creates feat/auth
381
395
```
382
396
383
397
| Flag | Description |
384
398
|------|-------------|
385
399
|`-b, --base <branch>`| Trunk branch (defaults to the repo's default branch) |
386
400
|`-a, --adopt`| Adopt existing branches instead of creating new ones |
387
-
|`-p, --prefix <string>`|Set a branch name prefix for auto-generated names|
401
+
|`-p, --prefix <string>`|Branch name prefix. Subsequent `add` calls only need the suffix (e.g., with `-p feat`, `gh stack add auth` creates `feat/auth`)|
388
402
389
403
**Behavior:**
390
404
405
+
- Using `-p` is recommended — it simplifies branch naming for subsequent `add` calls
391
406
- Creates any branches that don't already exist (branching from the trunk branch)
392
407
- In `--adopt` mode: validates all branches exist, rejects if any is already in a stack or has an existing PR
393
408
- Checks out the last branch in the list
@@ -406,7 +421,7 @@ gh stack add [branch] [flags]
406
421
**Recommended workflow — create the branch, then use standard git:**
407
422
408
423
```bash
409
-
# Create a new branch and switch to it
424
+
# Create a new branch and switch to it (just the suffix — prefix is applied automatically)
- When the current branch has no commits (e.g., right after `init`), `add -Am` commits directly on the current branch instead of creating a new one.
441
-
-If a prefix was set during `init`, the prefix is applied to branch names: `prefix/branch-name`.
456
+
-**Prefix handling:** Only pass the suffix when a prefix is set. `gh stack add api` with prefix `todo` → `todo/api`. Passing `todo/api` creates `todo/todo/api`. Without a prefix, pass the full branchname.
442
457
- If called from a branch that is not the topmost in the stack, exits with code 5: `"can only add branches on top of the stack"`. Use `gh stack top` to switch first.
443
458
-**Uncommitted changes:** When using `gh stack add branch-name` without `-Am`, any uncommitted changes (staged or unstaged) in your working tree carry over to the new branch. This is standard git behavior — the working tree is not touched. Commit or stash changes on the current branch before running `add` if you want a clean starting point on the new branch.
444
459
@@ -505,7 +520,7 @@ gh stack sync [flags]
505
520
506
521
1.**Fetch** latest changes from the remote
507
522
2.**Fast-forward trunk** to match remote (skips if already up to date, warns if diverged)
508
-
3.**Cascade rebase** all stack branches onto their updated parents (only if trunk moved). Handles squash-merged PRs automatically with `--onto`. If a conflict is detected, **all branches are restored** to their pre-rebase state and the command exits with code 3 — see [Handle rebase conflicts](#handle-rebase-conflicts-agent-workflow) for the resolution workflow
523
+
3.**Cascade rebase** all stack branches onto their updated parents (only if trunk moved). Handles squash-merged PRs automatically. If a conflict is detected, **all branches are restored** to their pre-rebase state and the command exits with code 3 — see [Handle rebase conflicts](#handle-rebase-conflicts-agent-workflow) for the resolution workflow
509
524
4.**Push** all active branches atomically
510
525
5.**Sync PR state** from GitHub and report the status of each PR
511
526
@@ -560,7 +575,7 @@ gh stack rebase --abort
560
575
561
576
**Conflict handling:** See [Handle rebase conflicts](#handle-rebase-conflicts-agent-workflow) in the Workflows section for the full resolution workflow.
562
577
563
-
**Squash-merge detection:** If a branch's PR was squash-merged on GitHub, the rebase automatically uses `git rebase --onto` to correctly replay commits on top of the merge target. This is handled transparently.
578
+
**Squash-merge detection:** If a branch's PR was squash-merged on GitHub, the rebase automatically handles this and correctly replays commits on top of the merge target.
564
579
565
580
**Rerere (conflict memory):**`git rerere` is enabled by `init` so previously resolved conflicts are auto-resolved in future rebases.
0 commit comments