Rewrite Changelog Entries Aggressively
Remove the changelog commits this branch accumulated, then regenerate
its entries from the branch's current net change. With --commit,
the regenerated entries land as one fresh commit at the tip; otherwise
they are left as an uncommitted edit for the user to commit. Where
the changelog-refresh skill stacks a correcting commit on top,
this skill rewrites the branch so its changelog
history collapses to a single clean commit.
Hard scope rule: only the branch's own changelog content is rewritten.
Changelog content from the base branch — earlier releases, or
unreleased entries from other work — is never modified. The branch's
code history is never modified either; only changelog commits are
touched.
Additional context from user: $ARGUMENTS
Phase 1: Safety checks and scope
Preconditions — refuse to proceed (report why) if any fail:
- Working tree dirty (
git status --porcelain non-empty)
- Detached HEAD, or an in-progress rebase/merge/cherry-pick
- Currently on the base/trunk branch
Detect the base. If the branch has a PR
(gh pr view --json baseRefName), the base is its baseRefName —
stack-aware. Otherwise detect trunk via
git symbolic-ref refs/remotes/origin/HEAD (fall back to master).
Find the changelog file the same way /changelog does (scan for
CHANGES, CHANGES.md, CHANGELOG.md, HISTORY.md, NEWS.md, …).
Partition the branch's commits touching the changelog file
(git log origin/<base>..HEAD --format='%h %s' -- <changelog-file>):
- Pure changelog commits — the commit's diff touches only the
changelog file. These will be dropped in Phase 2.
- Mixed commits — changelog hunks entangled with code changes.
These cannot be dropped wholesale. Ask via
ask-user-choice how
to handle each: leave the commit intact and let the new tip
commit supersede its entries (recommended — no code history
rewrite), or abort so the user can split the commit first.
- No changelog commits at all → nothing to rewrite; suggest
/changelog (or the changelog-refresh skill) and stop.
Pushed-branch gate. If the branch exists on the remote and the
commits to drop are pushed, warn that completing the rewrite will
require the user to git push --force-with-lease afterwards,
and get explicit confirmation before rewriting. This command never
pushes.
Back up. Record the current tip and create a backup branch:
git branch changelog-rewrite-backup-$(date -u +%Y%m%d-%H%M%SZ)
Report the backup branch name and SHA to the user.
Phase 2: Rebase out the old changelog commits
Drop the pure changelog commits non-interactively with a scripted
sequence editor — for example, turning their pick lines into
drop by SHA. With GNU coreutils:
GIT_SEQUENCE_EDITOR='sed -i -E "s/^pick (<sha1>|<sha2>)/drop \1/"' git rebase -i origin/<base>
On BSD/Darwin, -i requires an explicit backup suffix; without the
empty one it consumes -E as the suffix and litters the rebase
directory:
GIT_SEQUENCE_EDITOR='sed -i "" -E "s/^pick (<sha1>|<sha2>)/drop \1/"' git rebase -i origin/<base>
Use each dropped commit's abbreviated SHA exactly as it appears in
the todo list. On conflict, stop and show the state — never resolve
by discarding user code.
Verify the invariant before going further:
- Code unchanged:
git diff <backup> HEAD -- . ':(exclude)<changelog-file>' must be
empty (mixed commits kept intact keep this true by construction).
- If only pure commits were dropped and no mixed commits exist,
git diff origin/<base> HEAD -- <changelog-file> must now be
empty.
If either check fails, restore (git reset --hard <backup>), report,
and stop.
Phase 3: Regenerate entries fresh
Read the sibling command file
the changelog skill and apply its rules
verbatim — the Core Constraint (a branch is not a release), Phase 1
convention detection, Phase 2 commit categorization, Phase 3 entry
generation and voice, and its Phase 4 presentation gate — including the
per-entry voice check. Generate entries from the branch's current net
change against origin/<base>.
One exception: the sibling's Phase 4 offers the commit as a choice at
its approval panel. That choice does not carry here. --commit decides
what lands, it was passed or not before the rebase ran, and re-asking
after a history rewrite invites a yes that means something different
from the one the sibling collects.
Entries superseding a mixed commit's surviving changelog hunks may
update those hunks — they are branch-owned content — but nothing from
the base branch.
Phase 4: Present, edit, commit
Mandatory gate — never edit or commit without explicit approval.
- Present: the summary line
(
Branch: <name> | Base: <base> | Dropped: <shas> | Backup: <branch>),
the proposed entries as exact markdown, the insertion point, and the
Target: unreleased section line. This skill never touches version
headings or version files.
- On approval, apply with the Edit tool. With
--commit in
$ARGUMENTS, commit once at the tip, following the commit
message rules in the sibling command's Commit message conventions
for CHANGES edits — project convention first, fallback
docs(CHANGES) <what the update covers>, never a version, never a
#N in the message. Stage the changelog file explicitly by path —
never git add -A. Without --commit (the default), leave the
edit uncommitted and show a ready-to-use commit message built from
the same rules — committing is the user's decision, as with
/changelog.
- Close by reporting: the backup branch to delete once satisfied
(
git branch -D <backup>), that an uncommitted changelog edit is
awaiting the user's commit (when --commit was not passed), and —
if the branch was pushed — that the user needs
git push --force-with-lease to publish the rewrite.
Rules
- Backup before rewrite: the backup branch is created before any
rebase and its name reported; restoration is one
git reset --hard.
- Code history is sacred: only pure changelog commits are dropped;
mixed commits are never rewritten without an explicit user choice,
and the post-rebase code-diff check must come back empty.
- Branch-scoped, always: base-branch changelog content is never
modified.
- Commits only with
--commit: by default the regenerated entries
are left uncommitted with a suggested message; the rebase that drops
old changelog commits still runs (that is the point of this skill),
behind its own confirmation gates.
- Never pushes: force-pushing the rewritten branch is the user's
explicit act, flagged in the closing report.
- A branch is not a release: all Core Constraint rules from
/changelog apply — no version headings, no version predictions, no
version-file edits.
- Ask on ambiguity: mixed commits, unclear entry ownership, or a
pushed branch all get a question, not a guess.
Portability notes
ask-user-choice — present the listed options and wait for the user to pick one. Hosts with a structured multiple-choice tool (Claude Code's AskUserQuestion) should use it; otherwise print a numbered list and wait for a numbered reply. Never proceed on an assumed answer.
$ARGUMENTS — the text the user passed when invoking this skill. If your host does not substitute it, read it as the user's request in the current turn, and ask when there is none.
1---2name: changelog-rewrite-aggressively3description: Rebase out the branch's earlier changelog commits and regenerate its entries fresh; commits only with --commit4---56# Rewrite Changelog Entries Aggressively78Remove the changelog commits this branch accumulated, then regenerate9its entries from the branch's **current net change**. With `--commit`,10the regenerated entries land as one fresh commit at the tip; otherwise11they are left as an uncommitted edit for the user to commit. Where12the `changelog-refresh` skill stacks a correcting commit on top,13this skill rewrites the branch so its changelog14history collapses to a single clean commit.1516Hard scope rule: only the branch's own changelog content is rewritten.17Changelog content from the base branch — earlier releases, or18unreleased entries from other work — is never modified. The branch's19**code** history is never modified either; only changelog commits are20touched.2122Additional context from user: $ARGUMENTS2324---2526## Phase 1: Safety checks and scope27281. **Preconditions** — refuse to proceed (report why) if any fail:29 - Working tree dirty (`git status --porcelain` non-empty)30 - Detached HEAD, or an in-progress rebase/merge/cherry-pick31 - Currently on the base/trunk branch32332. **Detect the base.** If the branch has a PR34 (`gh pr view --json baseRefName`), the base is its `baseRefName` —35 stack-aware. Otherwise detect trunk via36 `git symbolic-ref refs/remotes/origin/HEAD` (fall back to `master`).37383. **Find the changelog file** the same way `/changelog` does (scan for39 `CHANGES`, `CHANGES.md`, `CHANGELOG.md`, `HISTORY.md`, `NEWS.md`, …).40414. **Partition the branch's commits** touching the changelog file42 (`git log origin/<base>..HEAD --format='%h %s' -- <changelog-file>`):43 - **Pure changelog commits** — the commit's diff touches only the44 changelog file. These will be dropped in Phase 2.45 - **Mixed commits** — changelog hunks entangled with code changes.46 These cannot be dropped wholesale. Ask via `ask-user-choice` how47 to handle each: leave the commit intact and let the new tip48 commit supersede its entries (recommended — no code history49 rewrite), or abort so the user can split the commit first.50 - No changelog commits at all → nothing to rewrite; suggest51 `/changelog` (or the `changelog-refresh` skill) and stop.52535. **Pushed-branch gate.** If the branch exists on the remote and the54 commits to drop are pushed, warn that completing the rewrite will55 require the **user** to `git push --force-with-lease` afterwards,56 and get explicit confirmation before rewriting. This command never57 pushes.58596. **Back up.** Record the current tip and create a backup branch:60 ```61 git branch changelog-rewrite-backup-$(date -u +%Y%m%d-%H%M%SZ)62 ```63 Report the backup branch name and SHA to the user.6465## Phase 2: Rebase out the old changelog commits66671. Drop the pure changelog commits non-interactively with a scripted68 sequence editor — for example, turning their `pick` lines into69 `drop` by SHA. With GNU coreutils:70 ```71 GIT_SEQUENCE_EDITOR='sed -i -E "s/^pick (<sha1>|<sha2>)/drop \1/"' git rebase -i origin/<base>72 ```73 On BSD/Darwin, `-i` requires an explicit backup suffix; without the74 empty one it consumes `-E` as the suffix and litters the rebase75 directory:76 ```77 GIT_SEQUENCE_EDITOR='sed -i "" -E "s/^pick (<sha1>|<sha2>)/drop \1/"' git rebase -i origin/<base>78 ```79 Use each dropped commit's abbreviated SHA exactly as it appears in80 the todo list. On conflict, stop and show the state — never resolve81 by discarding user code.82832. **Verify the invariant** before going further:84 - Code unchanged:85 `git diff <backup> HEAD -- . ':(exclude)<changelog-file>'` must be86 empty (mixed commits kept intact keep this true by construction).87 - If only pure commits were dropped and no mixed commits exist,88 `git diff origin/<base> HEAD -- <changelog-file>` must now be89 empty.9091 If either check fails, restore (`git reset --hard <backup>`), report,92 and stop.9394## Phase 3: Regenerate entries fresh9596Read the sibling command file97the `changelog` skill and apply its rules98verbatim — the *Core Constraint* (a branch is not a release), Phase 199convention detection, Phase 2 commit categorization, Phase 3 entry100generation and voice, and its Phase 4 presentation gate — including the101per-entry voice check. Generate entries from the branch's current net102change against `origin/<base>`.103104One exception: the sibling's Phase 4 offers the commit as a choice at105its approval panel. That choice does not carry here. `--commit` decides106what lands, it was passed or not before the rebase ran, and re-asking107after a history rewrite invites a yes that means something different108from the one the sibling collects.109110Entries superseding a mixed commit's surviving changelog hunks may111update those hunks — they are branch-owned content — but nothing from112the base branch.113114## Phase 4: Present, edit, commit115116**Mandatory gate — never edit or commit without explicit approval.**1171181. Present: the summary line119 (`Branch: <name> | Base: <base> | Dropped: <shas> | Backup: <branch>`),120 the proposed entries as exact markdown, the insertion point, and the121 `Target: unreleased section` line. This skill never touches version122 headings or version files.1232. On approval, apply with the Edit tool. **With `--commit`** in124 `$ARGUMENTS`, commit **once** at the tip, following the commit125 message rules in the sibling command's *Commit message conventions126 for CHANGES edits* — project convention first, fallback127 `docs(CHANGES) <what the update covers>`, never a version, never a128 `#N` in the message. Stage the changelog file explicitly by path —129 never `git add -A`. **Without `--commit`** (the default), leave the130 edit uncommitted and show a ready-to-use commit message built from131 the same rules — committing is the user's decision, as with132 `/changelog`.1333. Close by reporting: the backup branch to delete once satisfied134 (`git branch -D <backup>`), that an uncommitted changelog edit is135 awaiting the user's commit (when `--commit` was not passed), and —136 if the branch was pushed — that the user needs137 `git push --force-with-lease` to publish the rewrite.138139---140141## Rules142143- **Backup before rewrite**: the backup branch is created before any144 rebase and its name reported; restoration is one `git reset --hard`.145- **Code history is sacred**: only pure changelog commits are dropped;146 mixed commits are never rewritten without an explicit user choice,147 and the post-rebase code-diff check must come back empty.148- **Branch-scoped, always**: base-branch changelog content is never149 modified.150- **Commits only with `--commit`**: by default the regenerated entries151 are left uncommitted with a suggested message; the rebase that drops152 old changelog commits still runs (that is the point of this skill),153 behind its own confirmation gates.154- **Never pushes**: force-pushing the rewritten branch is the user's155 explicit act, flagged in the closing report.156- **A branch is not a release**: all Core Constraint rules from157 `/changelog` apply — no version headings, no version predictions, no158 version-file edits.159- **Ask on ambiguity**: mixed commits, unclear entry ownership, or a160 pushed branch all get a question, not a guess.161162163## Portability notes164165- `ask-user-choice` — present the listed options and wait for the user to pick one. Hosts with a structured multiple-choice tool (Claude Code's `AskUserQuestion`) should use it; otherwise print a numbered list and wait for a numbered reply. Never proceed on an assumed answer.166- `$ARGUMENTS` — the text the user passed when invoking this skill. If your host does not substitute it, read it as the user's request in the current turn, and ask when there is none.