Skip to content
OpenAgentsbeta
text
1# Changelog Generator — Workflow
2
3Turns a git commit range into a grouped, human-readable `CHANGELOG.md` entry: features,
4fixes, and breaking changes separated out, each linked to its issue/PR where possible.
5Works best on a history following Conventional Commits (see `openagents/commit-conventions`,
6listed as a soft dependency), but degrades gracefully on unstructured history too.
7
8Inputs: `from_ref` (required), `to_ref` (default `HEAD`), `version` (optional; section
9is labeled "Unreleased" if omitted).
10
11## Step 1 — Collect the commit range
12
13```bash
14git log <from_ref>..<to_ref> --pretty=format:'%H|%s|%b|%an' --no-merges
15```
16
17- Exclude merge commits (`--no-merges`) — they're usually noise for a changelog; if the
18 project's workflow is merge-commit-based instead of squash/rebase, adjust and include
19 merge commit subjects instead, but say so.
20- Also gather: `git diff <from_ref>..<to_ref> --stat` for a sanity check on scope, and
21 the repository's issue/PR URL pattern (from the remote `origin` URL) to build links.
22
23## Step 2 — Parse and classify each commit
24
25For each commit subject, extract `type(scope): summary` if it matches Conventional
26Commits. For commits that don't match the format:
27- Infer a type from the diff/summary content as a best effort (e.g. a summary starting
28 with "add" → likely `feat`; "fix"/"resolve" → `fix`).
29- Mark these as inferred (not explicit) — if the output format distinguishes, note it;
30 regardless, still classify rather than dropping them, since a changelog should
31 reflect all user-relevant history in the range, not just the well-formatted commits.
32
33Group by type:
34- `feat` → **Added** / **Features**
35- `fix` → **Fixed**
36- `perf` → **Performance**
37- `refactor`, `style`, `chore`, `build`, `ci`, `test` → generally omit from a
38 user-facing changelog (internal-only) *unless* the body indicates user-visible
39 impact — use judgment, don't include noise.
40- `docs` → **Documentation** (only if the project's changelog convention includes
41 docs; otherwise omit)
42- Anything with a `BREAKING CHANGE:` footer or `!` after the type/scope → **Breaking
43 Changes**, always included regardless of type, and always listed first within its
44 section.
45
46## Step 3 — Deduplicate and merge
47
48- Multiple commits that are really one logical change (e.g. a feature commit plus a
49 follow-up fix commit for the same feature within the range) should be merged into
50 one changelog line where that reads more clearly — use judgment, don't force it.
51- Revert commits that cancel out an earlier commit in the *same* range should cancel
52 each other out of the changelog entirely (net-zero user impact).
53
54## Step 4 — Add links
55
56For each entry, if the commit footer references an issue/PR number (`Fixes #123`,
57`Refs #456`) or the commit is reachable via a known PR (e.g. via `gh pr list --search
58<sha>` if `gh` is available), append a link: `([#123](<repo-url>/issues/123))`. If no
59reference is found, link the commit itself: `([abc1234](<repo-url>/commit/<sha>))`.
60Don't fabricate a link if neither is determinable — omit it for that entry instead.
61
62## Step 5 — Write the entry
63
64Follow [Keep a Changelog](https://keepachangelog.com/) structure:
65
66```markdown
67## [<version or "Unreleased">] - <YYYY-MM-DD, omit date if Unreleased>
68
69### Breaking Changes
70- <description of the break and migration path, if given in the commit body> ([#123](...))
71
72### Added
73- <summary, imperative→noun-phrase form, e.g. "add fuzzy search to package search"> ([#123](...))
74
75### Fixed
76- <summary> ([#456](...))
77
78### Performance
79- <summary> ([#789](...))
80```
81
82Omit any section with zero entries — don't print an empty `### Fixed` heading.
83
84Insert this new section at the top of `CHANGELOG.md`, directly under the file's H1
85title (create the file with a standard header if it doesn't exist yet). Do not
86reformat or reflow existing changelog entries below the insertion point.
87
88## Step 6 — Review pass
89
90Before finalizing, re-read the generated entries as a *user* of the project, not the
91author: does each line make sense without repo-internal context (variable names,
92internal file paths)? Rewrite any entry that only makes sense to someone who read the
93diff. Flag (but don't silently drop) any commit whose purpose is genuinely unclear from
94its message alone — list it under a `### Uncategorized` section at the bottom for a
95human to triage, rather than guessing at user-facing wording.
96
97## Stop conditions
98
99- `from_ref` doesn't exist or the range is empty → report this, don't generate an empty
100 section.
101- Range contains more than ~150 commits → note that the changelog may be coarse and
102 offer to summarize by theme instead of enumerating every commit.
103

Keyboard shortcuts

Focus search
/
Go to Explore
ge
Go to Home
gh
Go to Tags
gt
Go to Collections
gc
Show this help
?
Close suggestions or this dialog
Esc