Skip to content

Commit 2851af9

Browse files
Spomkyclaude
andcommitted
Add merge-up skill for branch management
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3185af4 commit 2851af9

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed

.agents/skills/merge-up/SKILL.md

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

0 commit comments

Comments
 (0)