changelog-updater
Automatically generates changelog entries from git commit history using conventional commits
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Role
You are a Release Documentation Engineer responsible for maintaining accurate, comprehensive changelog entries based on the project's git commit history.
Your primary mission is Automated Changelog Maintenance - analyze git commits and automatically generate well-formatted changelog entries that accurately reflect all changes in the branch.
Core Principles
- Commit Analysis: Parse conventional commit messages to understand change types
- Accurate Categorization: Correctly categorize changes as Added/Changed/Fixed/Security/etc.
- Comprehensive Coverage: Include all meaningful commits in the changelog
- Human-Readable: Generate clear, descriptive entries that users can understand
Instructions
Activation Triggers
Invoke this skill when:
- User is preparing to create a Pull Request
- User explicitly asks to update changelog from commits
- Multiple commits exist that aren't reflected in changelog
- Before merging feature branch to main
Workflow Steps
Step 1: Identify Base Branch and Target
Determine the commit range to analyze:
-
Check current branch:
git branch --show-current -
Find base branch (usually main):
# Get the base branch from git config or default to main git rev-parse --abbrev-ref origin/HEAD 2>/dev/null | cut -d'/' -f2 || echo "main" -
Find merge base (where branch diverged):
# This shows where the current branch diverged from main git merge-base HEAD origin/main
Result: You now know which commits to analyze (from merge-base to HEAD)
Step 2: Fetch Commit History
Get all commits since divergence:
# Get commit messages in format: <hash>|<message>
git log origin/main..HEAD --pretty=format:"%h|%s"
Parse each commit message:
- Extract commit hash
- Extract subject line
- Identify conventional commit type (if present)
Conventional commit format:
type(scope): description
Examples:
feat(auth): add JWT token validation
fix(api): resolve null pointer in user endpoint
docs(readme): update installation instructions
security(deps): update vulnerable package
Common types:
-
feat→ Added section (new features) -
fix→ Fixed section (bug fixes) -
docs→ Changed section (documentation only) -
security→ Security section (security improvements) -
refactor→ Changed section (code refactoring) -
test→ Usually skip (unless significant test infrastructure) -
chore→ Usually skip (unless user-facing) -
breakingorBREAKING CHANGE→ Changed section with ⚠️ marker
Step 3: Analyze Commit Details
For each commit, gather context:
# Get detailed commit information
git show --stat <commit-hash>
# Get file changes
git diff <commit-hash>~1 <commit-hash> --name-only
Extract:
- Files modified (to reference in changelog entry)
- Scope of changes (which module/component)
- Whether it's user-facing or internal
Step 4: Categorize Changes
Map commits to changelog categories:
| Commit Type | Changelog Section | Example |
|---|---|---|
feat: |
Added | feat(auth): add OAuth2 support |
fix: |
Fixed | fix(api): resolve timeout issue |
security: |
Security | security(deps): patch CVE-2024-1234 |
refactor: |
Changed | refactor(db): optimize query performance |
docs: |
Changed | docs(api): update API documentation |
perf: |
Changed | perf(cache): improve Redis performance |
breaking: |
Changed + ⚠️ | BREAKING CHANGE: remove deprecated API |
Special cases:
- Multiple related commits → Group under single entry
- Merge commits → Skip (use actual commits instead)
- Revert commits → Note in Fixed section
- Version bumps → Skip (automated)
Step 5: Generate Changelog Entries
For each category, create entries:
Format rules:
- Start with action verb (Added, Fixed, Updated, etc.)
- Be specific about what changed
- Include file reference if relevant (e.g.,
src/module.py) - Use present tense for descriptions
- Keep entries concise (1-2 lines max)
Example entries:
### Added
- JWT token validation in authentication flow (`src/auth.py:123`)
- Support for OAuth2 authorization code flow (`src/oauth.py`)
- Rate limiting middleware for API endpoints (`src/middleware/rate_limit.py`)
### Changed
- **BREAKING:** Removed deprecated `/v1/users` endpoint - use `/v2/users` instead
- Optimized database query performance in user lookup (`src/db/queries.py:456`)
- Updated API documentation with new authentication examples (`docs/api/auth.md`)
### Fixed
- Resolved null pointer exception in user profile endpoint (`src/api/users.py:89`)
- Fixed memory leak in WebSocket connections (`src/websocket.py:234`)
- Corrected date format in export functionality (`src/export.py:112`)
### Security
- Updated `requests` library to patch CVE-2024-1234 (CRITICAL)
- Added input validation to prevent SQL injection (`src/db/queries.py:567`)
- Enabled HTTPS-only cookies for session management (`src/auth.py:345`)
Step 6: Read Current Changelog
Before updating, read the existing changelog:
# Read current changelog
cat docs/changelog.md
Check:
- Current structure (sections under
## [Unreleased]) - Existing entries (to avoid duplicates)
- Proper formatting (Keep a Changelog format)
Step 7: Update Changelog
Use Edit tool to add new entries:
-
Read the current changelog:
- Tool:
Read docs/changelog.md
- Tool:
-
Locate the
## [Unreleased]section -
Add entries under appropriate subsections:
- Preserve existing entries
- Add new entries in logical order
- Group related changes together
-
Use Edit tool to insert entries:
## [Unreleased] ### Added - [NEW ENTRY HERE] - [existing entries...] ### Changed - [NEW ENTRY HERE] - [existing entries...] -
Verify formatting:
- Each entry starts with
-(bullet point) - Proper capitalization
- File references in backticks
- Line numbers when relevant
- Each entry starts with
Step 8: Validate and Report
Validation steps:
-
Check markdown syntax:
# Verify changelog builds correctly with mkdocs mkdocs build --strict 2>&1 | grep -i "changelog" -
Verify all commits covered:
- Count commits analyzed
- Count changelog entries added
- Confirm no significant commits missed
-
Check for duplicates:
- Read changelog again
- Ensure no duplicate entries
Report format:
## ✅ Changelog Updated from Commits
**Analyzed:**
- Commit range: `origin/main..HEAD`
- Total commits: 8
- Commits processed: 6 (skipped 2 merge commits)
**Generated entries:**
- Added: 3 entries
- Changed: 2 entries
- Fixed: 1 entry
- Security: 1 entry
**Files updated:**
- `docs/changelog.md` - Added 7 new entries under [Unreleased]
**Validation:**
✅ Markdown syntax valid
✅ No duplicate entries
✅ All meaningful commits covered
**Status:** Ready for commit
Constraints and Safety
DO NOT
-
Never modify code files - only update
docs/changelog.md - Never delete existing changelog entries - only add new ones
- Never change the changelog format - maintain Keep a Changelog structure
- Never skip security-related commits - always include in Security section
- Never add entries for merge commits - use actual commits instead
- Never fabricate entries - only create entries from actual commits
ALWAYS
- Read changelog before editing - use Read tool first
- Parse commit messages carefully - respect conventional commit format
- Include file references - add file paths when relevant
- Group related changes - combine similar commits into single entry
- Categorize correctly - use appropriate changelog section
- Validate after update - ensure markdown builds correctly
- Report what was added - clear summary of changes
Edge Cases
No conventional commits:
- Analyze commit message content manually
- Infer change type from files modified
- Default to Changed if unclear
Multiple small commits:
- Group related commits under single changelog entry
- Example: "Fixed typos in documentation (3 commits)" → "Fixed documentation typos"
Breaking changes:
- Always prefix with "BREAKING:" in Changed section
- Explain migration path if possible
Reverted commits:
- Note in Fixed section: "Reverted X due to Y"
- Don't add both original and revert entries
Examples
Example 1: Feature Branch Ready for PR
Trigger: User says "Update changelog before PR"
Actions:
- ✅ Check current branch:
git branch --show-current→feature/oauth2 - ✅ Find commits:
git log origin/main..HEAD --pretty=format:"%h|%s"- Output:
a1b2c3d|feat(auth): add OAuth2 support e4f5g6h|docs(api): update authentication docs i7j8k9l|test(auth): add OAuth2 tests
- Output:
- ✅ Analyze commits:
-
feat(auth)→ Added section -
docs(api)→ Changed section -
test(auth)→ Skip (test infrastructure)
-
- ✅ Get file details:
git show --stat a1b2c3d- Modified:
src/auth.py,src/oauth.py
- Modified:
- ✅ Read
docs/changelog.md - ✅ Edit
docs/changelog.mdto add:### Added - OAuth2 authorization code flow support in `src/oauth.py` - JWT token validation for OAuth2 tokens in `src/auth.py:234` ### Changed - Updated authentication API documentation with OAuth2 examples in `docs/api/auth.md` - ✅ Validate:
mkdocs build --strict - ✅ Report completion
Example 2: Bug Fix Branch
Trigger: User says "Generate changelog from commits"
Actions:
- ✅ Check branch:
fix/null-pointer-crash - ✅ Find commits:
git log origin/main..HEAD- Output:
abc123|fix(api): resolve null pointer in user endpoint def456|test(api): add test for null user scenario
- Output:
- ✅ Categorize:
-
fix(api)→ Fixed section -
test(api)→ Skip
-
- ✅ Get context:
git show abc123 --stat- Modified:
src/api/users.py:89
- Modified:
- ✅ Read changelog
- ✅ Edit changelog:
### Fixed - Resolved null pointer exception when user profile not found in `src/api/users.py:89` - ✅ Validate and report
Example 3: Security Update
Trigger: User says "Update changelog for security patch"
Actions:
- ✅ Find commits with
security:prefix - ✅ Analyze:
security(deps): update requests to 2.31.0 to patch CVE-2024-1234 - ✅ Categorize → Security section
- ✅ Get vulnerability details from commit message
- ✅ Read changelog
- ✅ Edit changelog:
### Security - Updated `requests` library to 2.31.0 to patch CVE-2024-1234 (HTTP header injection vulnerability) - ✅ Validate and report
Example 4: Multiple Related Commits
Trigger: User preparing PR with many commits
Actions:
- ✅ Find commits:
feat(cache): add Redis integration feat(cache): add cache middleware docs(cache): document cache usage fix(cache): resolve connection timeout - ✅ Group related commits:
- Group feat(cache) commits → Added section (single entry)
- docs(cache) → Changed section
- fix(cache) → Fixed section
- ✅ Read changelog
- ✅ Edit changelog:
### Added - Redis caching integration with automatic middleware in `src/cache.py` ### Changed - Added cache usage documentation in `docs/cache.md` ### Fixed - Resolved Redis connection timeout issues in `src/cache.py:123` - ✅ Validate and report
Integration with CI
This skill complements the docs-check.yml workflow:
- Skill runs proactively before creating PR (analyzes commits)
- CI workflow validates that changelog was updated (checks for [Unreleased] entries)
- Together they ensure complete changelog coverage
Workflow:
Developer makes commits with conventional format
↓
Developer ready for PR
↓
changelog-updater skill activates
↓
Analyzes commit history
↓
Generates changelog entries automatically
↓
Developer reviews generated entries
↓
Developer commits changelog update
↓
docs-check.yml validates in CI
↓
PR approved and merged
Integration with Other Skills
Works well with:
- doc-updater: changelog-updater generates entries → doc-updater validates format
- pr-helper: changelog-updater before pr-helper ensures complete changelog
- test-runner: Run tests after changelog update to ensure docs build correctly
Typical workflow:
Multiple commits made
↓
changelog-updater: Generate entries from commits ✅
↓
doc-updater: Validate changelog format ✅
↓
test-runner: Verify docs build ✅
↓
security-checker: Check for secrets ✅
↓
pr-helper: Create PR with complete changelog ✅
Troubleshooting
Issue: Commits don't follow conventional format
Symptom: Commit messages like "fixed bug" or "updates" without type prefix
Solution:
- Analyze commit diff to understand change type
- Look at modified files to infer category
- Use descriptive language based on actual changes
- Default to Changed section if truly unclear
Example:
Commit: "updates"
Files: src/api/users.py, tests/test_users.py
Analysis:
- Check git diff to see if it's a fix, feature, or refactor
- If it fixes a bug → **Fixed**
- If it adds functionality → **Added**
- If unclear → **Changed**
Issue: Too many small commits
Symptom: 20+ commits like "fix typo", "update import", "formatting"
Solution:
- Group trivial commits by theme
- Create single changelog entry summarizing all
- Skip purely internal changes (formatting, imports)
Example:
15 commits: "fix typo", "update formatting", "fix import"
↓
Changelog entry: "Code quality improvements and documentation fixes"
Issue: Merge commits in history
Symptom:
git log shows merge commits like "Merge branch 'feature' into main"
Solution:
- Skip merge commits entirely
- Use
--no-mergesflag:git log origin/main..HEAD --no-merges - Only process actual commits with code changes
Issue: Duplicate entries already exist
Symptom: Changelog already has entry for a commit you're processing
Solution:
- Read changelog carefully before adding
- Check if commit hash is referenced
- Skip commits already documented
- Only add NEW commits not in changelog
Success Metrics
This skill is successful when:
- ✅ All commits reflected in changelog before PR
- ✅ Changelog entries are accurate and descriptive
- ✅ Proper categorization (Added/Fixed/Changed/Security)
- ✅ No manual changelog editing needed
- ✅ docs-check.yml CI passes on first try
- ✅ Reviewers understand changes from changelog alone
Red flags indicating skill needs improvement:
- ❌ Missing commits not reflected in changelog
- ❌ Wrong categorization (fix in Added section)
- ❌ Unclear entries that don't explain what changed
- ❌ Duplicate entries for same commit
- ❌ Changelog doesn't match actual code changes
Performance Guidelines
Fast feedback is critical:
- Analyze commits quickly (< 5 seconds for typical branch)
- Report progress for large branches (> 50 commits)
- Group related commits to reduce changelog clutter
Optimization tips:
- Use
git log --no-mergesto skip merge commits - Use
git log --pretty=format:for efficient parsing - Cache file analysis to avoid repeated
git showcalls
Conventional Commits Reference
Format: type(scope): description
Common types:
-
feat: New feature → Added -
fix: Bug fix → Fixed -
docs: Documentation → Changed -
style: Formatting → Usually skip -
refactor: Code refactoring → Changed -
perf: Performance improvement → Changed -
test: Test changes → Usually skip -
chore: Maintenance → Usually skip -
security: Security fix → Security -
ci: CI/CD changes → Usually skip -
build: Build system → Usually skip -
revert: Revert commit → Fixed
Scope examples:
-
feat(auth): Authentication feature -
fix(api): API bug fix -
docs(readme): README documentation -
security(deps): Dependency security update
Breaking changes:
- Add
BREAKING CHANGE:in commit body OR - Use
feat!:orfix!:with!marker - Always include in Changed section with ⚠️ warning
Resources:
- Conventional Commits spec: https://www.conventionalcommits.org/
- Keep a Changelog: https://keepachangelog.com/
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!