Skip to content

Commit c9c1e98

Browse files
Spomkyclaude
andcommitted
Add merge-up skill for cascade branch merging
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent cc2f8f0 commit c9c1e98

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

.claude/commands/merge-up.md

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
---
2+
description: >
3+
Cascade-merge maintained branches from oldest to newest (e.g.
4+
5.2.x -> 5.3.x). Use when the user says "merge up", "cascade merge",
5+
"sync branches", or "merge branches".
6+
---
7+
8+
# WebAuthn Framework Branch Cascade Merge
9+
10+
Merges each maintained branch into the next one, from oldest to newest.
11+
12+
## Progress checklist
13+
14+
- [ ] Step 0: Pre-flight checks
15+
- [ ] Step 1: Fetch maintained branches and pull them
16+
- [ ] Step 2: Cascade merge loop
17+
18+
---
19+
20+
## Confirmation rule
21+
22+
Whenever the skill says **"Wait for confirmation"**, treat anything other than an
23+
explicit affirmative as **no**: stop and ask the user how they want to proceed.
24+
25+
---
26+
27+
## Step 0 — Pre-flight checks
28+
29+
```bash
30+
git status --porcelain --untracked-files=no
31+
```
32+
33+
If any output, **stop**:
34+
> "The working tree is not clean. Please commit or stash your changes first."
35+
36+
---
37+
38+
## Step 1 — Fetch maintained branches and pull them
39+
40+
### 1a. Get the branch list
41+
42+
The maintained branches follow the pattern `<major>.<minor>.x`. Determine them from:
43+
44+
```bash
45+
git branch -r --list 'origin/*.x' --sort=version:refname
46+
```
47+
48+
Filter to only the actively maintained branches (typically the two most recent minor
49+
version lines). Store as `BRANCHES`, sorted oldest to newest.
50+
51+
If the user specifies which branches to merge (e.g. "merge 5.2.x into 5.3.x"),
52+
use exactly those branches instead.
53+
54+
### 1b. Pull every branch
55+
56+
For each branch in `BRANCHES`:
57+
58+
```bash
59+
git checkout <branch>
60+
git pull --ff-only origin <branch>
61+
```
62+
63+
Using `--ff-only` ensures local branches haven't diverged from origin. If the
64+
pull fails, **stop** and report the error.
65+
66+
---
67+
68+
## Step 2 — Cascade merge loop
69+
70+
For each consecutive pair `(SOURCE, TARGET)` in `BRANCHES`:
71+
72+
### 2a. Merge
73+
74+
```bash
75+
git checkout <TARGET>
76+
git merge <SOURCE>
77+
```
78+
79+
Three outcomes are possible:
80+
81+
- **Already up-to-date:** print "Already up-to-date with `<SOURCE>`"
82+
and skip to the next pair.
83+
- **Clean merge (no conflicts):** git creates the merge commit automatically.
84+
Proceed directly to step 2c.
85+
- **Conflicts:** proceed to step 2b.
86+
87+
### 2b. Resolve conflicts (only when git reports conflicts)
88+
89+
List conflicts:
90+
91+
```bash
92+
git diff --name-only --diff-filter=U
93+
```
94+
95+
Read each conflicted file, resolve it, then `git add` it. When all are resolved:
96+
97+
```bash
98+
git commit --no-edit
99+
```
100+
101+
#### Conflict resolution rules
102+
103+
| File pattern | Strategy |
104+
|---|---|
105+
| `CHANGELOG*.md` | Keep entries from both sides; newer branch entries on top |
106+
| Version constants, `composer.json` branch aliases | Keep the TARGET branch value |
107+
| `composer.json` dependency versions | Keep the TARGET branch value (higher) |
108+
| Code files | Merge logically based on context; when unsure, ask the user |
109+
110+
After resolving, show `git diff HEAD~1` (first parent of the merge commit, i.e.
111+
the previous TARGET state) and wait for the user to confirm the resolution looks
112+
correct before proceeding.
113+
114+
### 2c. Run tests for affected areas
115+
116+
Determine what changed:
117+
118+
```bash
119+
git diff --name-only HEAD~1..HEAD
120+
```
121+
122+
Run tests based on what was affected:
123+
124+
**PHP tests:**
125+
```bash
126+
castor phpunit
127+
```
128+
129+
If the full suite is too slow and only specific areas changed, run targeted tests:
130+
```bash
131+
vendor/bin/phpunit tests/framework/
132+
vendor/bin/phpunit tests/library/
133+
vendor/bin/phpunit tests/symfony/functional/
134+
```
135+
136+
**Static analysis (if PHP files changed):**
137+
```bash
138+
castor phpstan
139+
castor ecs
140+
```
141+
142+
**JavaScript tests (if JS/TS files changed under src/stimulus/):**
143+
```bash
144+
npm test
145+
```
146+
147+
If tests fail, first check whether the failure is pre-existing: run the same
148+
test on the TARGET branch before the merge. Only fix failures introduced by the merge:
149+
1. Analyze and fix the code.
150+
2. Commit the fix with a descriptive message.
151+
3. Re-run failing tests until green.
152+
153+
Report any pre-existing failures to the user without attempting to fix them.
154+
155+
### 2d. Ask for confirmation before pushing
156+
157+
Show:
158+
159+
```
160+
Merge: <SOURCE> -> <TARGET>
161+
Tests: all passing
162+
163+
Commits since origin/<TARGET>:
164+
git log --oneline origin/<TARGET>..<TARGET>
165+
166+
Ready to push? (yes / no)
167+
```
168+
169+
**Wait for confirmation.** The user may make changes themselves before confirming.
170+
171+
### 2e. Push and continue
172+
173+
```bash
174+
git push origin <TARGET>
175+
```
176+
177+
If the push fails, **stop** and report the error.
178+
179+
Print "`<SOURCE>` -> `<TARGET>` done." and continue to the next pair.
180+
181+
---
182+
183+
## Final summary
184+
185+
```
186+
All merges complete:
187+
5.2.x -> 5.3.x done
188+
```
189+
190+
---
191+
192+
## Gotchas
193+
194+
- `CHANGELOG.md` conflicts are the most common; entries must be kept from both
195+
sides, never dropped.
196+
- A merge can introduce test failures even without conflicts, because behavior
197+
from the older branch may be incompatible with newer code. Always run tests.
198+
- `composer.json` may have different version constraints between branches; always
199+
keep the TARGET (newer) branch values for branch aliases and self-version.
200+
201+
## Error handling
202+
203+
- **Never** force-push or rewrite history.
204+
- **Never** use `--no-verify` on commits.
205+
- **Never** auto-recover from a failed `git push` or `git pull`. Stop and hand
206+
control back to the user.

0 commit comments

Comments
 (0)