change-log-generator
Change Log Generator
Automatically generate comprehensive change logs from git history and code changes.
Core Capabilities
This skill helps create change logs by:
- Analyzing git commits - Parse commit messages for changes
- Processing conventional commits - Extract structured information from standardized commits
- Examining diffs/patches - Understand code changes from git diff output
- Categorizing changes - Automatically group by type (features, fixes, docs, etc.)
- Formatting output - Generate Markdown change logs following best practices
Change Log Generation Workflow
Step 1: Gather Change Information
Collect commits and changes for the release period.
Determine Release Range:
# Changes since last tag
git log $(git describe --tags --abbrev=0)..HEAD --oneline
# Changes between two tags
git log v1.2.0..v1.3.0 --oneline
# Changes in last N commits
git log -n 50 --oneline
# Changes since specific date
git log --since="2024-01-01" --oneline
# Changes in current branch vs main
git log main..HEAD --oneline
Get Detailed Commit Information:
# Full commit messages
git log v1.2.0..HEAD --format="%H|%an|%ad|%s|%b" --date=short
# With file changes
git log v1.2.0..HEAD --name-status
# With diff stats
git log v1.2.0..HEAD --stat
Get Pull Request Information:
# Using GitHub CLI
gh pr list --state merged --base main --limit 50
# Get PR details
gh pr view 123 --json title,body,labels,mergedAt
Step 2: Parse Commit Messages
Extract meaningful information from commits.
Conventional Commit Format:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Common Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, missing semicolons, etc.)refactor: Code refactoringperf: Performance improvementstest: Adding or updating testsbuild: Build system or external dependency changesci: CI configuration changeschore: Other changes that don't modify src or test files
Examples:
feat(auth): add OAuth2 authentication
Implements OAuth2 authentication flow using Google provider.
Users can now sign in with their Google accounts.
Closes #45
fix(api): prevent race condition in user creation
Race condition occurred when multiple requests tried to create
the same user simultaneously. Added database constraint and
retry logic.
Fixes #123
docs: update installation instructions
Added troubleshooting section for Windows users.
BREAKING CHANGE: remove deprecated API endpoints
The /api/v1/users endpoint has been removed. Use /api/v2/users instead.
Parse Commit Messages:
import re
def parse_conventional_commit(message):
"""Parse conventional commit message."""
# Pattern: type(scope): description
pattern = r'^(\w+)(\(([^)]+)\))?:\s*(.+)$'
match = re.match(pattern, message)
if match:
return {
'type': match.group(1),
'scope': match.group(3),
'description': match.group(4),
'breaking': 'BREAKING CHANGE' in message
}
else:
return {
'type': 'other',
'scope': None,
'description': message,
'breaking': 'BREAKING CHANGE' in message
}
# Example
commit = "feat(auth): add OAuth2 authentication"
parsed = parse_conventional_commit(commit)
# Returns: {'type': 'feat', 'scope': 'auth', 'description': 'add OAuth2 authentication', 'breaking': False}
See references/conventional_commits.md for detailed parsing rules.
Step 3: Categorize Changes
Group commits by change type.
Category Mapping:
CATEGORIES = {
'feat': {
'title': 'Features',
'emoji': 'โจ',
'description': 'New features and capabilities'
},
'fix': {
'title': 'Bug Fixes',
'emoji': '๐',
'description': 'Bug fixes and corrections'
},
'perf': {
'title': 'Performance',
'emoji': 'โก',
'description': 'Performance improvements'
},
'refactor': {
'title': 'Refactoring',
'emoji': 'โป๏ธ',
'description': 'Code refactoring'
},
'docs': {
'title': 'Documentation',
'emoji': '๐',
'description': 'Documentation updates'
},
'test': {
'title': 'Testing',
'emoji': 'โ
',
'description': 'Test additions and updates'
},
'build': {
'title': 'Build System',
'emoji': '๐๏ธ',
'description': 'Build and dependency changes'
},
'ci': {
'title': 'CI/CD',
'emoji': '๐ท',
'description': 'CI/CD changes'
},
'style': {
'title': 'Code Style',
'emoji': '๐',
'description': 'Code style and formatting'
},
'chore': {
'title': 'Chores',
'emoji': '๐ง',
'description': 'Maintenance and chores'
}
}
def categorize_commits(commits):
"""Categorize commits by type."""
categorized = {}
for commit in commits:
parsed = parse_conventional_commit(commit['message'])
commit_type = parsed['type']
if commit_type not in categorized:
categorized[commit_type] = []
categorized[commit_type].append({
'description': parsed['description'],
'scope': parsed['scope'],
'sha': commit['sha'][:7],
'author': commit['author'],
'breaking': parsed['breaking']
})
return categorized
Prioritize Categories:
Order of importance:
- Breaking Changes (always first)
- Features
- Bug Fixes
- Performance
- Security
- Deprecations
- Other categories
Step 4: Format Change Log
Generate Markdown output following conventions.
Basic Template:
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
### Added
- New feature A
- New feature B
### Changed
- Updated component X
- Improved performance of Y
### Deprecated
- Old API endpoint will be removed in v2.0
### Removed
- Deprecated feature Z
### Fixed
- Bug in authentication flow
- Memory leak in processor
### Security
- Fixed XSS vulnerability in input validation
Generate Changelog Entry:
def generate_changelog_entry(version, date, categorized_commits):
"""Generate changelog entry for a version."""
lines = []
# Header
lines.append(f"## [{version}] - {date}\n")
# Breaking Changes (if any)
breaking_changes = []
for category, commits in categorized_commits.items():
for commit in commits:
if commit.get('breaking'):
breaking_changes.append(commit)
if breaking_changes:
lines.append("### โ ๏ธ BREAKING CHANGES\n")
for change in breaking_changes:
scope_str = f"**{change['scope']}**: " if change['scope'] else ""
lines.append(f"- {scope_str}{change['description']} ({change['sha']})")
lines.append("")
# Regular categories
category_order = ['feat', 'fix', 'perf', 'refactor', 'docs', 'test', 'build', 'ci', 'style', 'chore']
for cat_type in category_order:
if cat_type in categorized_commits:
category_info = CATEGORIES.get(cat_type, {'title': cat_type.title()})
lines.append(f"### {category_info['title']}\n")
for commit in categorized_commits[cat_type]:
if commit.get('breaking'):
continue # Already listed in breaking changes
scope_str = f"**{commit['scope']}**: " if commit['scope'] else ""
lines.append(f"- {scope_str}{commit['description']} ([`{commit['sha']}`](link/to/commit/{commit['sha']}))")
lines.append("")
return "\n".join(lines)
Example Output:
## [1.3.0] - 2024-02-15
### โ ๏ธ BREAKING CHANGES
- **api**: remove deprecated /v1/users endpoint (a1b2c3d)
### Features
- **auth**: add OAuth2 authentication support ([`d4e5f6g`](link))
- **dashboard**: add real-time metrics visualization ([`h7i8j9k`](link))
- **api**: implement rate limiting for API endpoints ([`l0m1n2o`](link))
### Bug Fixes
- **auth**: prevent race condition in user creation ([`p3q4r5s`](link))
- **ui**: fix button alignment on mobile devices ([`t6u7v8w`](link))
- **api**: handle null values in request validation ([`x9y0z1a`](link))
### Performance
- **database**: optimize user query with indexes ([`b2c3d4e`](link))
- **api**: implement caching for frequently accessed data ([`f5g6h7i`](link))
### Documentation
- update installation instructions ([`j8k9l0m`](link))
- add troubleshooting guide ([`n1o2p3q`](link))
Step 5: Handle Special Cases
Address non-conventional commits and edge cases.
Non-Conventional Commits:
def categorize_non_conventional(message):
"""Categorize commits that don't follow conventional format."""
message_lower = message.lower()
# Keyword-based categorization
if any(word in message_lower for word in ['add', 'implement', 'create']):
return 'feat'
elif any(word in message_lower for word in ['fix', 'resolve', 'correct', 'patch']):
return 'fix'
elif any(word in message_lower for word in ['update', 'improve', 'enhance']):
return 'refactor'
elif any(word in message_lower for word in ['doc', 'readme', 'comment']):
return 'docs'
elif any(word in message_lower for word in ['test', 'spec']):
return 'test'
else:
return 'other'
Merge Commits:
# Exclude merge commits
git log --no-merges v1.2.0..HEAD
# Or include merge commits with special handling
git log --first-parent v1.2.0..HEAD
Pull Request Integration:
def extract_pr_info(commit_message):
"""Extract PR number from commit message."""
# Pattern: (#123) or Merge pull request #123
import re
match = re.search(r'#(\d+)', commit_message)
if match:
return match.group(1)
return None
def enhance_with_pr_data(commit, pr_number):
"""Enhance commit with PR metadata."""
# Use gh CLI or GitHub API
import subprocess
import json
result = subprocess.run(
['gh', 'pr', 'view', pr_number, '--json', 'title,labels,author'],
capture_output=True,
text=True
)
if result.returncode == 0:
pr_data = json.loads(result.stdout)
commit['pr_title'] = pr_data.get('title')
commit['pr_labels'] = pr_data.get('labels', [])
commit['pr_author'] = pr_data.get('author', {}).get('login')
return commit
Step 6: Add Metadata and Links
Enrich changelog with helpful information.
Add Comparison Links:
## [1.3.0] - 2024-02-15
[Full Changelog](https://github.com/user/repo/compare/v1.2.0...v1.3.0)
### Features
...
Add Contributors:
# Get unique contributors
git log v1.2.0..v1.3.0 --format="%an <%ae>" | sort | uniq
## [1.3.0] - 2024-02-15
**Contributors:** @alice, @bob, @charlie
### Features
...
Add Issue References:
def extract_issue_refs(message):
"""Extract issue references from commit message."""
import re
# Patterns: #123, Closes #123, Fixes #123
patterns = [
r'#(\d+)',
r'[Cc]loses?\s+#(\d+)',
r'[Ff]ixes?\s+#(\d+)',
r'[Rr]esolves?\s+#(\d+)'
]
issues = set()
for pattern in patterns:
matches = re.findall(pattern, message)
issues.update(matches)
return list(issues)
# Format in changelog
# - Fix authentication bug (closes #123, #124)
Step 7: Validate and Publish
Review and finalize the changelog.
Validation Checklist:
- All significant changes included
- Breaking changes clearly marked
- Changes categorized correctly
- Links working (commits, PRs, issues)
- Version number follows semantic versioning
- Date is correct
- Contributors acknowledged
- No duplicate entries
- Formatting consistent
Update CHANGELOG.md:
# Prepend new entry to existing CHANGELOG.md
cat new_entry.md CHANGELOG.md > temp.md
mv temp.md CHANGELOG.md
# Commit the changelog
git add CHANGELOG.md
git commit -m "docs: update changelog for v1.3.0"
Create GitHub Release:
# Using gh CLI
gh release create v1.3.0 \
--title "Version 1.3.0" \
--notes-file new_entry.md
# Or manually via GitHub web interface
Quick Templates
Minimal Template
## [1.3.0] - 2024-02-15
### Added
- OAuth2 authentication
- Real-time metrics
### Fixed
- Race condition in user creation
- Mobile UI alignment
### Changed
- Optimized database queries
- Updated dependencies
Standard Template
## [1.3.0] - 2024-02-15
[Full Changelog](https://github.com/user/repo/compare/v1.2.0...v1.3.0)
### โ ๏ธ BREAKING CHANGES
- **api**: Removed deprecated /v1/users endpoint. Migrate to /v2/users ([#145](link))
### Features
- **auth**: Add OAuth2 authentication support ([#142](link)) @alice
- **dashboard**: Real-time metrics visualization ([#143](link)) @bob
### Bug Fixes
- **auth**: Prevent race condition in user creation ([#144](link)) @alice
- **ui**: Fix button alignment on mobile ([#146](link)) @charlie
### Performance
- **database**: Optimize user queries with indexes ([#147](link))
**Contributors:** @alice, @bob, @charlie
Comprehensive Template
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
### In Progress
- Feature X under development
- Performance improvements being tested
## [1.3.0] - 2024-02-15
[Full Changelog](https://github.com/user/repo/compare/v1.2.0...v1.3.0) | [Release Notes](link)
> **Highlights:** This release adds OAuth2 authentication and significantly improves performance.
### โ ๏ธ BREAKING CHANGES
- **api**: Removed deprecated /v1/users endpoint
- **Migration Guide:** Replace `/v1/users` with `/v2/users` in your API calls
- **Impact:** Applications using the old endpoint will receive 404 errors
- See [Migration Guide](link) for details
### โจ Features
- **auth**: Add OAuth2 authentication support ([`a1b2c3d`](link)) ([#142](link))
- Supports Google and GitHub providers
- Automatic account creation on first login
- Thanks to @alice for implementation
- **dashboard**: Real-time metrics visualization ([`d4e5f6g`](link)) ([#143](link))
- Live update every 5 seconds
- Customizable dashboard widgets
- **api**: Implement rate limiting ([`h7i8j9k`](link)) ([#148](link))
- 100 requests per minute per IP
- Configurable via environment variables
### ๐ Bug Fixes
- **auth**: Prevent race condition in user creation ([`l0m1n2o`](link)) ([#144](link))
- Fixed duplicate user creation
- Added database constraint
- **ui**: Fix button alignment on mobile devices ([`p3q4r5s`](link)) ([#146](link))
- **api**: Handle null values in validation ([`t6u7v8w`](link)) ([#149](link))
### โก Performance
- **database**: Optimize user queries with indexes ([`x9y0z1a`](link)) ([#147](link))
- 70% faster user lookups
- Reduced database load
- **api**: Implement response caching ([`b2c3d4e`](link)) ([#150](link))
- 50% reduction in API response time
### ๐ Documentation
- Update installation instructions ([`f5g6h7i`](link))
- Add troubleshooting guide ([`j8k9l0m`](link))
- Improve API documentation ([`n1o2p3q`](link))
### ๐๏ธ Build System
- Update dependencies to latest versions ([`r4s5t6u`](link))
- Add Docker support for development ([`v7w8x9y`](link))
### ๐งช Testing
- Add integration tests for auth flow ([`z0a1b2c`](link))
- Improve test coverage to 85% ([`d3e4f5g`](link))
### ๐ท CI/CD
- Add automated deployment to staging ([`h6i7j8k`](link))
- Implement security scanning in CI ([`l9m0n1o`](link))
**New Contributors:**
- @alice made their first contribution in #142
- @bob improved the dashboard in #143
**Full Contributor List:** @alice, @bob, @charlie, @david
**Download:** [v1.3.0 Release](link)
---
## [1.2.0] - 2024-01-15
[Previous release notes...]
Automation Scripts
Generate Changelog Script
#!/bin/bash
# generate_changelog.sh - Generate changelog between two tags
FROM_TAG=${1:-$(git describe --tags --abbrev=0 HEAD^)}
TO_TAG=${2:-HEAD}
VERSION=${3:-"Unreleased"}
DATE=$(date +%Y-%m-%d)
echo "# Changelog Entry for $VERSION"
echo ""
echo "## [$VERSION] - $DATE"
echo ""
# Get commits
git log $FROM_TAG..$TO_TAG --format="%s" --no-merges | while read commit; do
# Parse conventional commit
if [[ $commit =~ ^([a-z]+)(\(([^)]+)\))?:\ (.+)$ ]]; then
type="${BASH_REMATCH[1]}"
scope="${BASH_REMATCH[3]}"
desc="${BASH_REMATCH[4]}"
case $type in
feat)
echo "### Features" >> /tmp/feat.txt
echo "- $desc" >> /tmp/feat.txt
;;
fix)
echo "### Bug Fixes" >> /tmp/fix.txt
echo "- $desc" >> /tmp/fix.txt
;;
docs)
echo "### Documentation" >> /tmp/docs.txt
echo "- $desc" >> /tmp/docs.txt
;;
esac
fi
done
# Output in order
for file in /tmp/{feat,fix,docs}.txt; do
if [ -f "$file" ]; then
cat "$file" | sort | uniq
echo ""
rm "$file"
fi
done
See references/automation_examples.md for more complete scripts.
Best Practices
- Use conventional commits - Makes categorization automatic
- Include issue/PR references - Provides context and traceability
- Highlight breaking changes - Critical for users upgrading
- Keep entries concise - One line per change, link to details
- Use present tense - "Add feature" not "Added feature"
- Group by category - Easier to scan and understand
- Add migration guides - For breaking changes
- Link to commits/PRs - Enables deeper investigation
- Acknowledge contributors - Recognize team efforts
- Update regularly - Don't wait until release day
Resources
references/conventional_commits.md- Detailed guide to conventional commit format and parsing rulesreferences/keep_a_changelog.md- Keep a Changelog format specification and examplesreferences/automation_examples.md- Complete scripts for automating changelog generation
Quick Reference
| Task | Command |
|---|---|
| Commits since last tag | git log $(git describe --tags --abbrev=0)..HEAD |
| Commits between tags | git log v1.2.0..v1.3.0 |
| No merge commits | git log --no-merges |
| With file changes | git log --name-status |
| Contributors | git log --format="%an" | sort | uniq |
| PR info | gh pr view 123 --json title,body |
| Create release | gh release create v1.3.0 --notes-file changelog.md |
Common Patterns
Pattern 1: Quick release notes
git log v1.2.0..v1.3.0 --oneline --no-merges | \
sed 's/^[a-f0-9]* /- /' > release_notes.md
Pattern 2: Group by author
git log v1.2.0..v1.3.0 --format="%an: %s" --no-merges | \
sort | uniq
Pattern 3: Extract breaking changes
git log v1.2.0..v1.3.0 --format="%B" --no-merges | \
grep -A 5 "BREAKING CHANGE"