Generate release notes from git commit history.
# With npm
npm install --save-dev @definitely-not-devs/notegen
# With pnpm
pnpm add -D @definitely-not-devs/notegen
# With yarn
yarn add -D @definitely-not-devs/notegen# With npm
npm install -g @definitely-not-devs/notegen
# With pnpm
pnpm add -g @definitely-not-devs/notegen
# With yarn
yarn global add @definitely-not-devs/notegenWith global installation, use notegen directly without npx.
- Initialize configuration:
npx notegen initThis creates a notegen.json file in your project:
{
"baseUrl": "https://jira.company.com/browse",
"releaseNotes": true,
"output": "CHANGELOG.md"
}- Generate release notes:
npx notegen generate# Generate release notes for all commits
npx notegen generate
# Or add to package.json scripts:
{
"scripts": {
"release-notes": "notegen generate"
}
}
# Then run:
pnpm release-notes# Specify output file
npx notegen generate -o CHANGELOG.md
# Generate for specific commit range
npx notegen generate --from v1.0.0 --to v2.0.0
# Generate for a specific tag (auto-detects previous tag)
npx notegen generate --to v2.0.0
# Generate for the latest tag (auto-detects last and previous tag)
npx notegen generate --last --release-notes
# Limit number of commits
npx notegen generate --limit 10
# Generate release notes format (grouped by feat/fix with tickets)
npx notegen generate --release-notes
# With ticket links
npx notegen generate --release-notes --base-url https://jira.company.com/browse-o, --output <file>- Output file path (default:RELEASE_NOTES.md)-f, --from <commit>- Start from commit/tag (exclusive)-t, --to <commit>- End at commit/tag (inclusive, default:HEAD)-l, --limit <number>- Limit number of commits-r, --release-notes- Generate release notes format with grouped tickets (feat/fix)--no-release-notes- Generate standard changelog format (overrides config)-b, --base-url <url>- Base URL for linking tickets--last- Generate release notes for the last tag (auto-detects previous tag)
CLI options override configuration file settings.
Commits are processed in reverse chronological order (newest to oldest). This ensures the most recent changes appear first in your release notes.
The tool automatically handles revert commits to keep your release notes accurate:
How it works:
- Detects revert commits - Identifies commits starting with "Revert" or "revert"
- Extracts reverted tickets - Finds ticket references (US-123, BUG-456, etc.) in the revert commit
- Removes earlier commits - Filters out commits with those ticket IDs that came before the revert
- Preserves newer commits - Keeps commits with the same ticket ID if they came after the revert
Example timeline:
# Commit history (oldest to newest)
git commit -m "feat: add feature US-123" # ✗ Will be removed
git commit -m "Revert: feat US-123" # ✗ Revert itself removed
git commit -m "feat: re-add feature US-123" # ✓ Kept (after revert)Result: Only the final implementation of US-123 appears in release notes.
Supported revert formats:
# Standard git revert
Revert "feat: add feature US-123"
# Manual revert with ticket in message
revert: remove feature US-123
# Revert with ticket in body
Revert "feat: add feature"
US: 123This prevents duplicate or incorrect entries when features are reverted and re-implemented.
All release notes are automatically grouped by version tags. The tool uses git describe to associate each commit with its nearest reachable tag.
How it works:
- For each commit, the tool finds the most recent tag that contains it
- Commits are grouped by version first, then by section type
- Versions are sorted from newest to oldest
- Commits without tags appear under "Untagged"
Example structure:
## 2.0.0
### User Stories
- US 1
- US 2
### Bugs
- BUG 1
- BUG 2
## 1.9.0
### User Stories
- US 3
- US 4
### Bugs
- BUG 3
- BUG 4This structure makes it easy to see what changed in each version and generate release notes for specific releases.
Groups commits by conventional commit prefixes and scopes, organized by version:
feat(api): add user authentication
fix(ui): resolve login bug
chore: update dependenciesGenerates a hierarchical changelog grouped by version:
## 2.0.0
### Features
#### api
- add user authentication
#### ui
- update dashboard
### Bug Fixes
#### api
- resolve login bug
## 1.0.0
### Features
#### core
- initial releaseCommits are grouped by version first (detected from git tags), then by type (feat/fix/other), then by scope. Commits without a scope appear under "Other". Commits without a version tag appear under "Untagged".
Custom sections from config are not used in basic mode.
If your config has "releaseNotes": true by default, you can override it with --no-release-notes to use basic mode.
Groups commits by ticket references for tracking, organized by version. The ticket reference can be in either the commit message or body:
# In commit message (single -m)
git commit -m "feat: add user authentication US-123"# In commit footer (multiple -m or editor)
feat: add user authentication
US: 123fix: resolve login bug
BUG: 456In release notes mode, commits are grouped by version first (detected from git tags), then by ticket reference type (US, BUG, etc.).
Supported ticket formats:
- Numeric:
US123,US 123,US-123,US:123,US#123 - Alphanumeric:
JIRA-ABC-123,BUG_456,US-2024-789 - Multiple tickets per commit:
US 234 & BUG 456(each ticket gets its own line) - Mixed types:
US 234, BUG 456(appears in both User Stories and Bugs sections)
Requirements:
- Pattern must be a complete word (e.g.,
USwon't match inFOCUS) - Ticket ID must contain at least one digit
- Supports custom patterns defined in your config
Commits without matching ticket references are excluded from release notes mode.
You can configure custom sections in notegen.json:
{
"sections": [
{
"section": "User Stories",
"pattern": "US",
"label": "US"
},
{
"section": "Bugs",
"pattern": "BUG",
"label": "BUG"
},
{
"section": "Improvements",
"pattern": "IMPROVEMENT",
"label": "IMPROVEMENT"
}
]
}Each section matches commits based on ticket references in either the commit message or body.
Pattern matching rules:
- The
patternmust match as a complete word (word boundaries enforced) - Ticket IDs must contain at least one digit
- Flexible separators: space, dash, colon, or no separator
- Supports alphanumeric ticket IDs (e.g.,
JIRA-ABC-123) - Multiple tickets in one commit will create separate entries
Example patterns:
USmatches:US123,US-123,US 123,US:123,US#123,US-ABC-123BUGmatches:BUG456,BUG-456,BUG_789- Won't match:
FOCUS 123(US is not a complete word),US for(no digit)
Git History:
git commit -m "feat: add login feature" -m "US: 100"
git commit -m "fix: resolve auth bug" -m "BUG: 200"
git commit -m "feat: add dashboard" -m "US: 101"
git commit -m "Revert: fix auth" -m "BUG: 200" # Reverting BUG-200
git commit -m "fix: proper auth fix" -m "BUG: 200" # Re-implementing BUG-200Command:
npx notegen generate --release-notesOutput (RELEASE_NOTES.md):
# RELEASE NOTES
Generated: 2024-01-15
## 2.0.0
### User Stories
- US 100
- US 101
### Bugs
- BUG 200
---
**Total:** 3 item(s)What happened:
- Original BUG-200 fix was removed (reverted)
- Revert commit itself was removed
- New BUG-200 fix is kept (after revert)
- All US items kept (not reverted)
Git History:
git commit -m "feat(auth): implement OAuth US-500"
git commit -m "feat(auth): add token refresh US-500"
git commit -m "fix(auth): handle edge case US-500"
git commit -m "Revert feat: OAuth not ready" -m "US: 500"
git commit -m "feat(api): add REST endpoints US-501"
git commit -m "feat(auth): implement SAML US-500" # New approachCommand:
npx notegen generate --release-notes --base-url https://jira.company.com/browseOutput:
# RELEASE NOTES
Generated: 2024-01-15
## 3.0.0
### User Stories
- [US 500](https://jira.company.com/browse/500)
## 2.5.0
### User Stories
- [US 501](https://jira.company.com/browse/501)
---
**Total:** 2 item(s)What happened:
- First 3 commits with US-500 removed (OAuth implementation reverted)
- US-501 kept (different ticket)
- Final US-500 commit kept (SAML implementation after revert)
Git History:
git commit -m "feat: combined feature" -m "US: 600\nUS: 601"
git commit -m "fix: combined fixes" -m "BUG: 700\nBUG: 701"
git commit -m "Revert: feature not ready" -m "US: 600" # Only revert US-600Output:
# RELEASE NOTES
Generated: 2024-01-15
## 1.5.0
### User Stories
- US 601
### Bugs
- BUG 700
- BUG 701
---
**Total:** 3 item(s)What happened:
- US-600 removed (reverted)
- US-601 kept (same commit, but different ticket - not reverted)
- All bug fixes kept (not reverted)
Command:
npx notegen generate --from v1.0.0 --to v2.0.0 --release-notesOnly processes commits between v1.0.0 and v2.0.0, applying revert logic within that range. Reverts outside the range don't affect commits inside the range.