Skip to content

Commit 4b6bdda

Browse files
committed
docs on rebase workflow
1 parent 0706796 commit 4b6bdda

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

docs/src/content/docs/guides/workflows.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,106 @@ This command:
137137

138138
If a conflict is detected during the rebase, all branches are restored to their original state, and you're advised to run `gh stack rebase` to resolve conflicts interactively.
139139

140+
## Rebasing Your Stack
141+
142+
Stacked PRs rely on rebasing rather than merge commits to keep each branch's diff clean and reviewable. If you're coming from a merge-commit workflow, the key difference is: instead of merging upstream changes into your branch (which creates a merge commit with multiple parents), you replay your commits on top of the latest base. The result is a linear history where each PR shows only its specific changes.
143+
144+
### How rebasing works with stacks
145+
146+
When you run `gh stack rebase`, it performs a **cascading rebase**: each branch in the stack is rebased onto the tip of the branch below it, starting from the trunk. This ensures every branch has the latest changes from all lower layers.
147+
148+
```sh
149+
# Rebase the entire stack (all branches, trunk to top)
150+
gh stack rebase
151+
152+
# Only rebase from trunk up to the current branch
153+
gh stack rebase --downstack
154+
155+
# Only rebase from the current branch up to the top
156+
gh stack rebase --upstack
157+
```
158+
159+
After rebasing, push the updated branches:
160+
161+
```sh
162+
gh stack push
163+
```
164+
165+
`gh stack push` uses `--force-with-lease` to safely update the rebased branches. This is a safe form of force push — it ensures you don't overwrite changes that someone else pushed since your last fetch. If the remote has unexpected changes, the push is rejected and you can investigate.
166+
167+
### Rebase from the CLI vs. the web UI
168+
169+
You can rebase stack branches from either the CLI or the GitHub web UI, but they behave differently:
170+
171+
| | CLI (`gh stack rebase`) | Web UI ("Rebase Stack" button) |
172+
|---|---|---|
173+
| **Runs where** | Locally, using your Git installation | On GitHub's servers |
174+
| **Commit signing** | Commits are signed with your local Git committer config (GPG/SSH signing, if configured) | Commits retain the original author but the committer is set to whoever clicked the button — commits are **not** signed |
175+
| **Conflict resolution** | Interactive — you resolve conflicts in your editor, then `gh stack rebase --continue` | Not available if there are conflicts — you must rebase locally |
176+
177+
If commit signing matters for your project (e.g., branch protection rules require signed commits), use the CLI for rebases.
178+
179+
### Resolving conflicts
180+
181+
When a rebase encounters a conflict, `gh stack rebase` stops and tells you which files are conflicted:
182+
183+
```sh
184+
gh stack rebase
185+
# ✗ Conflict detected rebasing feat/api onto feat/auth
186+
# C api/routes.go (lines 12–18)
187+
#
188+
# Resolve conflicts on feat/api, then run: gh stack rebase --continue
189+
# Or abort this operation with: gh stack rebase --abort
190+
```
191+
192+
To resolve:
193+
194+
```sh
195+
# 1. Open the conflicted files and resolve the markers
196+
# (<<<<<<< / ======= / >>>>>>>)
197+
# Use your editor of choice
198+
199+
# 2. Stage the resolved files
200+
git add api/routes.go
201+
202+
# 3. Continue the rebase — remaining branches are rebased automatically
203+
gh stack rebase --continue
204+
```
205+
206+
If the conflict is too complex or you want to start over:
207+
208+
```sh
209+
# Abort and restore all branches to their pre-rebase state
210+
gh stack rebase --abort
211+
```
212+
213+
### The rebase + force-push cycle
214+
215+
The typical cycle when updating a stack after making changes looks like this:
216+
217+
```sh
218+
# 1. Make changes on a mid-stack branch
219+
gh stack checkout feat/auth
220+
git add .
221+
git commit -m "Fix token validation"
222+
223+
# 2. Rebase everything above to incorporate the change
224+
gh stack rebase --upstack
225+
226+
# 3. Push all updated branches (safe force push)
227+
gh stack push
228+
```
229+
230+
This is equivalent but distinct from updating your branch using a merge commit. The key difference is that after changing a lower branch, rebase maintains a linear commit history so the unique set of commits on each branch have clean diffs.
231+
232+
`gh stack push` then handles the force push safely via `--force-with-lease --atomic`, ensuring either all branches update or none do.
233+
234+
For a simpler all-in-one flow, `gh stack sync` combines fetch, rebase, and push into a single command — useful when you just need to pull in the latest upstream changes:
235+
236+
```sh
237+
gh stack sync
238+
```
239+
140240
## Existing Branches into a Stack
141241

142242
If you already have a set of branches that form a logical chain, you can organize them into a stack by passing them to `gh stack init`. Existing branches are adopted automatically — no special flags needed.

0 commit comments

Comments
 (0)