Skip to content

Commit 7f407be

Browse files
Phlogistiqueclaude
andauthored
Simplify README to focus on workflow (#3)
* Simplify README: less laudative, more straightforward explanation * Soften claims, fix action reference, restore credits --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7c994b2 commit 7f407be

1 file changed

Lines changed: 25 additions & 42 deletions

File tree

README.md

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,33 @@
1-
## README – Updating Stacked PRs After a Squash‑Merge
1+
## Stacked PRs with squash & merge
22

3-
### Why this script exists
4-
When you work with **stacked pull‑requests**—a chain of feature branches where each PR is based on the previous one—life is good right up to the moment the bottom PR is merged with **"Squash & Merge."**
5-
A squash merge rewrites history and then deletes the source branch, which breaks every open PR that depended on it.
3+
### The problem
64

7-
**Pain points the script eliminates**
5+
If you want stacked pull requests on GitHub, one way to do it that stays easy for people who aren't rebase wizards is to use a simple `git push` / `git merge` workflow while working on your PRs.
86

9-
| Pain | Why it happens | Consequence in GitHub UI |
10-
|------|----------------|---------------------------|
11-
| 1. **Descendant branches lose their base** | The commit they were branched from no longer exists on the target branch. | GitHub shows a red *"This branch is out‑of‑date with the base branch"* banner. |
12-
| 2. **Diffs are garbage** | GitHub compares the child‑branch to `main`, not to the commit it actually diverged from. | Reviewers see a giant diff containing code from *all* earlier PRs, making review impossible. |
13-
| 3. **"Update branch" button explodes** | The missing commits mean Git can't perform a clean rebase or merge. | Clicking *Update branch* opens a web conflict‑editor with dozens of unrelated hunks. |
14-
| 4. **Manual recovery is tedious** | Each branch must be rebased/merged and force‑pushed one‑by‑one. | Hours of menial work and risk of errors. |
7+
When you merge the lower PR in the stack, you just need to update the upper PR. This works fine if you use regular merge commits, but your trunk history becomes very hard to read with normal tooling like the GitHub commit history page (though you can still navigate it with `git log --first-parent`).
158

16-
This action automates that recovery:
17-
1. Replays the missing history onto every direct child PR with a synthetic three‑parent merge.
18-
2. Recursively updates indirect descendants so they stay clean and reviewable.
19-
3. Updates each PR's base branch so GitHub's diff & merge logic are correct.
20-
4. Deletes the merged branch.
9+
If you use squash & merge instead, your main branch history stays nice and clean, but now the upper PR in the stack gets a garbage diff and merge conflicts when you try to update it. This happens because the squash commit rewrites history, and GitHub can't figure out what the PR is actually trying to change.
2110

22-
The net result: **your stack stays green and reviewers only see the intended diff**.
11+
### The solution
12+
13+
This action tries to fix that in a transparent way. Install it, and hopefully the workflow of stacking + merge during dev + squash merge when landing works.
2314

2415
---
2516

26-
### How the action works (high level)
27-
1. **Trigger** – Fires when a PR is closed *and* `merged == true` *and* has `merge_commit_sha` (i.e. a squash merge).
28-
2. **Discover hierarchy** – Uses `gh pr list` to find PRs whose `base` was the merged branch; walks the tree recursively.
29-
3. **Direct children** – For each child branch it creates a synthetic merge commit that records three parents: (a) the child's old tip, (b) the deleted branch tip, (c) the squash commit. This preserves history without re‑introducing code.
30-
4. **Indirect descendants** – Simply merge the now‑updated parent branch; no custom commit needed.
31-
5. **PR metadata** – Switches each direct child PR's base to the trunk branch (or next living base).
32-
6. **Push & clean up** – Force‑pushes updated branches where necessary and deletes the obsolete branch on the remote.
17+
### How it works
18+
19+
1. Triggers when a PR is squash merged
20+
2. Finds PRs that were based on the merged branch
21+
3. For direct children: creates a synthetic merge commit with three parents (child tip, deleted branch tip, squash commit) to preserve history without re-introducing code
22+
4. For indirect descendants: merges the updated parent branch
23+
5. Updates each PR's base branch to point to trunk
24+
6. Force-pushes updated branches and deletes the merged branch
3325

3426
---
3527

36-
### Using this action in your repository
28+
### Setup
3729

38-
#### As a GitHub Action workflow
39-
1. Create a `.github/workflows/update-pr-stack.yml` file with the following content:
30+
Create a `.github/workflows/update-pr-stack.yml` file:
4031
```yaml
4132
name: Update Stacked PRs on Squash Merge
4233

@@ -60,27 +51,19 @@ jobs:
6051
fetch-depth: 0
6152

6253
- name: Update PR stack
63-
uses: username/test-stack@v1
54+
uses: Phlogistique/autorestack-action@main
6455
env:
6556
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6657
```
67-
2. Replace `username/test-stack@v1` with the appropriate repository reference (e.g., `your-username/your-repo@main` or use a version tag).
6858
69-
#### Repository contents
70-
| File | Purpose |
71-
|------|---------|
72-
| `update-pr-stack.sh` | Bash script that performs all git/gh operations. |
73-
| `.github/workflows/update-pr-stack.yml` | GitHub Actions workflow that runs the script after every squash merge. |
74-
| `action.yml` | GitHub Action definition for reuse in other repositories. |
59+
### Notes
7560
76-
---
77-
78-
### Caveats & Tips
79-
* Only supports **squash merges** for the base PR.
80-
* TODO: If a merge in the chain hits a conflict the workflow exits neutral, comments on the PR, and waits for the developer to resolve & push. A follow‑up label or comment automatically resumes the stack update.
81-
* Very large stacks may hit GitHub rate limits; TODO: throttle or batch API calls if needed.---
61+
* Currently only supports squash merges
62+
* If a merge hits a conflict, you'll need to resolve it manually
63+
* Very large stacks might hit GitHub rate limits
8264
8365
---
8466
8567
### Credits
86-
Inspired by *Graphite* and *Gerrit* workflows but implemented with plain git + GitHub CLI.
68+
69+
Inspired by Graphite and Gerrit workflows but implemented with plain git + GitHub CLI.

0 commit comments

Comments
 (0)