Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Sponsored Reserved space — layout preview until AdSense is connected

How to Generate Release Notes from Git Commit Messages in Python

This script fetches recent Git commit messages using conventional commit prefixes (feat, fix, etc.), categorizes them, and prints formatted release notes with today's date.

Medium Python 3.9+ Jun 28, 2026 Git + Python 2 views 0 copies

Python code

55 lines
Python 3.9+
import subprocess
import re
from datetime import datetime

def get_git_log(since_tag="HEAD~10", format_str="%s"):
    """Retrieve commit messages from git log."""
    try:
        result = subprocess.run(
            ["git", "log", f"--since={since_tag}", f"--format={format_str}"],
            capture_output=True,
            text=True,
            check=True
        )
        return result.stdout.strip().split("\n")
    except subprocess.CalledProcessError:
        return []

def categorize_commit(msg):
    """Categorize commit message by conventional commit prefix."""
    patterns = {
        "Features": r"^feat(?:\(.*?\))?:",
        "Bug Fixes": r"^fix(?:\(.*?\))?:",
        "Refactoring": r"^refactor(?:\(.*?\))?:",
        "Documentation": r"^docs(?:\(.*?\))?:",
        "Chores": r"^chore(?:\(.*?\))?:"
    }
    for category, pattern in patterns.items():
        if re.match(pattern, msg, re.IGNORECASE):
            return category
    return "Other Changes"

def generate_release_notes():
    """Main function to produce release notes from git history."""
    messages = [m for m in get_git_log() if m.strip()]
    if not messages:
        print("No commit messages found.")
        return

    categories = {}
    for msg in messages:
        cat = categorize_commit(msg)
        # Remove the prefix for cleaner output
        clean_msg = re.sub(r"^(feat|fix|refactor|docs|chore)(\(.*?\))?:\s*", "", msg, flags=re.IGNORECASE).strip()
        categories.setdefault(cat, []).append(clean_msg)

    print(f"## Release Notes ({datetime.now().strftime('%Y-%m-%d')})\n")
    for category, items in categories.items():
        if items:
            print(f"### {category}")
            for item in items:
                print(f"- {item}")
            print()

if __name__ == "__main__":
    generate_release_notes()

Output

stdout
## Release Notes (2025-04-05)

### Features
- add user authentication endpoint
- implement dark mode toggle

### Bug Fixes
- fix login redirect loop
- correct typo in welcome message

### Refactoring
- simplify database connection logic

### Other Changes
- update readme with setup instructions

How it works

The script uses subprocess.run to safely execute git log and capture commit messages. A categorize_commit function applies regex patterns based on the Conventional Commits specification (feat, fix, etc.). After stripping the prefix for readability, commits are grouped by category inside a dictionary. Finally, the output is formatted as Markdown with a heading that includes the current date via datetime.now().

Common mistakes

  • Running the script outside a Git repository will cause a `CalledProcessError` and return an empty list.
  • Misspelled conventional commit prefixes (e.g., 'fixx' instead of 'fix') will fall to 'Other Changes'.
  • Forgetting to strip the prefix from the commit message can lead to duplicate text like 'feat: feat: add login'.

Variations

  1. Use `--since=<tag>` with a git tag name instead of `HEAD~10` to generate notes for a specific release.
  2. Replace the plain print formatting with output to a markdown file using `pathlib.Path.write_text()`.

Real-world use cases

  • Automating changelog generation for a CI/CD pipeline before every deployment.
  • Creating a monthly release summary for an open-source project's contributors.
  • Feeding structured commit data into a documentation site or an internal wiki.

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

Related tutorials and quizzes for this topic.