Tutorials & Guides
How to Build an Automated Git Changelog Generator with Gemini Flash and Python
Curating high-quality release notes from messy git commit logs is incredibly tedious. Here is how to automate categorised, human-readable changelogs using Gemini Flash's cost-effective API.
Updated 9/2/2026
Stop Shipping Raw Commit Logs to Your Users
We have all seen release notes that look like this: - Update index.js - Fixed typo - WIP: fixing CSS breakages - Forgot to import ref
This kind of log is useful when you are hunting down a regression, but it is utterly useless to your product team, stakeholders, or end-users. A proper changelog should group features, bug fixes, performance improvements, and chores into clean, human-readable sections.
Doing this manually before a release is a chore that developers love to procrastinate on. But with /platforms/gemini, we have access to an extremely fast, cheap, and long-context LLM that is perfect for parsing text-heavy datasets like git logs and returning structured summaries.
In this step-by-step tutorial, we will build a local Python utility that grabs the commit history since your last release tag, filters the noise, and uses Gemini Flash to write a production-ready changelog.
Why Gemini Flash for Developer Tooling?
While /platforms/openai is highly capable, Gemini 1.5 Flash shines when it comes to raw processing speed and exceptionally low API costs for developers running frequent automated workflows. Its massive context window also means you don’t have to worry if your team has committed 2,000 times between releases—you can feed the entire raw git history in, and Gemini won't blink.
Setup and Installation
You will need a Google Gemini API key to proceed. Head to the Google AI Studio to grab one, then install the official Google Generative AI SDK along with gitpython to easily handle programmatic Git commands inside our Python script.
`bash
pip install google-generativeai gitpython python-dotenv
`
Ensure your project contains a .env file containing your key:
`env
GEMINI_API_KEY=your_gemini_api_key_here
`
Step 1: Extracting Git Commits Programmatically
We need to extract the commits between two git tags. If no tags exist yet, we will default to extracting the last 30 commits to test our logic.
Create a script named changelog_generator.py and start by writing our git retrieval function:
`python
import os
from git import Repo
from dotenv import load_dotenv
import google.generativeai as genai
load_dotenv() genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
def get_git_commits(repo_path="."): try: repo = Repo(repo_path) except Exception as e: print(f"Could not open Git repository: {e}") return []
Retrieve tags sorted by commit date tags = sorted(repo.tags, key=lambda t: t.commit.committed_datetime) commit_list = [] if len(tags) >= 1: # If we have tags, get commits from the latest tag up to the current HEAD latest_tag = tags[-1] print(f"Generating changelog for commits since tag: {latest_tag.name}") commits = list(repo.iter_commits(f"{latest_tag.name}..HEAD")) else: # Fallback to the last 30 commits if no tag exists print("No tags found. Analyzing the last 30 commits...") commits = list(repo.iter_commits(max_count=30)) for commit in commits: # Clean up the message and save the short SHA and author name clean_msg = commit.message.strip().split('\n')[0] commit_list.append({ "sha": commit.hexsha[:7], "author": commit.author.name, "message": clean_msg }) return commit_list ```
Step 2: Defining the Gemini Flash Pipeline
Now, we need to design a system instruction that forces Gemini Flash to structure our output into logical, readable groups while ignoring the standard garbage commits that clutter active repos.
We will structure our prompt to output markdown format. Let's add the generation logic to our file:
`python
SYSTEM_PROMPT = """
You are a helpful release engineer. Your job is to transform raw, messy git commits into a clean, human-readable changelog for software releases.
When given a list of commits, group them into the following strict categories: - 🚀 New Features: Real functionality added to the codebase. - 🐛 Bug Fixes: Stability improvements, UI correction, or error handling adjustments. - ⚙️ Performance & Refactoring: Code cleanups, underlying library updates, speed optimisations. - 🧹 Chores & Maintenance: Changes to configuration, test suites, or package versions.
Rules to live by: 1. Ignore trivial commits that add no user-facing value, such as 'typo fixes', 'WIP', 'updated index', or 'forgot semicolon'. 2. Rewrite vague commit messages into professional summaries. 3. Keep the layout concise. Bullet points are essential. 4. Do not include any greeting or explanation. Start directly with the markdown changelog header. """
def generate_changelog(commits):
if not commits:
print("No new commits to analyze.")
return ""
# Format commits into a clean text block for the LLM input
formatted_commits = ""
for c in commits:
formatted_commits += f"- [{c['sha']}] {c['message']} (by {c['author']})\n"
model = genai.GenerativeModel(
model_name="gemini-1.5-flash",
system_instruction=SYSTEM_PROMPT
)
# Setting low temperature to prioritize consistent, structured output
generation_config = {
"temperature": 0.1,
"max_output_tokens": 2000,
}
print("Querying Gemini Flash to process logs...")
response = model.generate_content(
f"Analyze the following git commits and compile a changelog:\n\n{formatted_commits}",
generation_config=generation_config
)
return response.text
`
Step 3: Tying it All Together
Finally, we will add a small command-line execution wrapper to save the output straight to a file or print it directly to stdout.
`python
if __name__ == "__main__":
commits = get_git_commits()
if commits:
changelog = generate_changelog(commits)
print("\n--- GENERATED CHANGELOG ---\n")
print(changelog)
# Optional: Save it directly to an output file for review
with open("DRAFT_CHANGELOG.md", "w") as f:
f.write(changelog)
print("Changelog saved successfully as DRAFT_CHANGELOG.md")
else:
print("No commits found to process.")
`
Example Output
If you have a set of commits like:
* b348f9a Added oauth authentication flow
* f2010c3 Fixes memory leak on user session disconnect
* d2994e1 fix: minor text layout in profile page
* e0018a1 wip: styling things
Gemini Flash will discard the wip commits and generate a clean output like this:
`markdown
# Release Changelog
🚀 New Features - Added OAuth authentication flow to allow secure user login option ([b348f9a]).
🐛 Bug Fixes - Resolved a critical memory leak that occurred during user session disconnection ([f2010c3]). - Corrected a minor text layout misalignment on the user profile screen ([d2994e1]). ```
Customisation & Next Steps
Now that you have a functioning script, you can hook it into your development workflow in several ways:
- Git Hooks: Save this script inside your repository, and create a
pre-pushorpre-releasegit hook that automatically generates theDRAFT_CHANGELOG.mdfile before you finalize your tag releases. - CI/CD Pipeline: Integrate this directly into your GitHub Actions or GitLab pipelines. When a new tag is pushed, have the runner run this Python script, and use the markdown output to automatically populate the release details using the platform's API.
If you encounter any API issues or authentication errors while configuring your keys, make sure to check the developer docs over on the Gemini Developer Support Portal to verify your billing and service configurations.
Now you can spend less time editing raw git messages and more time shipping code!
Keep going
Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.