A good release notes template saves you from starting every release with a blank page, and it keeps your notes in the same shape every time so readers know where to look. This guide gives you a copy-ready template, a fully filled-in example, and a short, tested way to pull the raw list of changes from git so you are editing, not remembering.
The git commands below were run on 13 November 2026 (git 2.49) against a sample repository we built for this guide, and the output shown is the real output. The filled-in example is for a fictional product, Acme Billing, and was checked line by line against that repository’s commits and against Semantic Versioning rules.
TL;DR
- Lead with a one-to-three sentence Highlights section. Most readers stop there.
- Group changes under fixed headings: New, Improved, Fixed, Deprecated, Breaking changes, Known issues, Action required.
- Write each item from the user’s side: what they can now do, or what stopped going wrong. Not the internal ticket title.
- Draft from
git logbetween the last two tags, then delete anything users will not notice. - Put deprecations and anything users must do in their own sections, so nobody misses them.
Release Notes vs Changelog: What Is the Difference?
The terms are often used interchangeably, but they serve different readers. A changelog is a complete, chronological record of notable changes, usually kept in a CHANGELOG.md file and aimed at developers. The Keep a Changelog convention groups entries under Added, Changed, Deprecated, Removed, Fixed and Security, with an Unreleased section at the top.
Release notes are written for the people who use a specific release. They are selective, explain impact in plain language, and tell readers what to do next. In practice, many teams keep a changelog in the repository and publish release notes, built from it, on their docs site, in the app or in an email.
| Changelog | Release notes | |
|---|---|---|
| Audience | Developers and contributors | Users, customers, admins, support |
| Coverage | Every notable change | Changes that matter to users |
| Tone | Short, factual entries | Plain language, explains the benefit |
| Where it lives | CHANGELOG.md in the repo | Docs site, in-app, email, app store |
The Release Notes Template (Copy-Ready)
Copy this into your docs tool, a Markdown file or your release form. Delete sections that are empty for a given release, except Breaking changes, where “None” is useful information.
# [Product name] [version number]
Released: [YYYY-MM-DD]
## Highlights
[One to three sentences on the change most users will care about, and why.]
## New
- [Feature]: [what users can now do, in one sentence]. [Link to docs]
## Improved
- [Area]: [what is better, with a number if you have one].
## Fixed
- [What was broken, described as the user saw it]. [Ticket or issue link]
## Deprecated
- [Feature or endpoint] is deprecated and will be removed in [version]. Use [replacement] instead. [Migration guide link]
## Breaking changes
- [What no longer works the old way] and [what to do about it].
## Known issues
- [Problem], [who it affects], [workaround if any].
## Action required
1. [Step users or admins must take to upgrade, if any.]
## Links
- Full changelog: [link]
- Documentation: [link]
- Support: [link]What goes in each section
| Section | What to write | Common mistake |
|---|---|---|
| Title and date | Product name, version, release date in YYYY-MM-DD | Leaving out the date, so readers cannot tell how current it is |
| Highlights | The one or two changes most users care about, and why | Listing everything again |
| New | New capabilities, one sentence each, with a docs link | Internal names (“Project Falcon”) instead of what it does |
| Improved | Better performance, usability or limits; add a number if you measured one | Vague claims such as “various improvements” |
| Fixed | The bug as users experienced it | Pasting the ticket title (“NPE in AuthSvc”) |
| Deprecated | What is going away, when, and what replaces it | No removal version or replacement |
| Breaking changes | What stops working the old way and how to adapt | Hiding it in the Improved list |
| Known issues | Open problems, who they affect, any workaround | Omitting them; support then hears it first |
| Action required | Numbered steps users or admins must take | Burying required steps in prose |
Filled-In Release Notes Example
Here is the template filled in for a fictional invoicing product. Every item under New, Improved, Fixed and Deprecated maps to a commit in the sample repository used in the next section. The docs-only commit was left out because users would not notice it.
# Acme Billing 2.4.0
Released: 2026-11-13
## Highlights
You can now export invoices to CSV and download any invoice as a PDF
through the API, so month-end reporting no longer needs manual copying.
## New
- CSV export: export any filtered invoice list from Invoices > Export.
- Invoice PDFs in the API: GET /v2/invoices/{id}/pdf returns the invoice
as a PDF file.
## Improved
- Search: filter counts are now cached, so changing filters on large
accounts responds faster.
## Fixed
- You are no longer signed out straight after resetting your password.
- The date picker no longer closes when you scroll inside it.
## Deprecated
- GET /v1/reports is deprecated and will be removed in version 3.0.0.
Use GET /v2/reports instead.
## Breaking changes
- None in this release.
## Known issues
- CSV exports of more than 50,000 rows can time out. Workaround: narrow
the date range and export in batches.
## Action required
1. If you call GET /v1/reports, move to GET /v2/reports before
upgrading to 3.0.0.
## Links
- Full changelog: v2.3.0...v2.4.0
- Documentation: docs.example.com/billing
- Support: support.example.comNotice how it stays consistent with Semantic Versioning: 2.4.0 is a minor release, so it adds features and deprecates an endpoint but does not remove anything. The removal of GET /v1/reports is a breaking change, so it waits for 3.0.0, and the notes say so in both the Deprecated and Action required sections. The Known issues entry is the one part that does not come from git; it comes from QA and support.
How to Write Release Notes Step by Step
- Collect the changes. Pull the commit or pull request list since the last release (commands below), plus anything from your issue tracker that shipped.
- Remove the noise. Delete refactors, test changes, dependency bumps and docs fixes that users will never notice.
- Sort into sections. New, Improved, Fixed, Deprecated, Breaking changes. If a change does not fit any section, ask whether users need to hear about it.
- Rewrite each item for the reader. “Fix race condition in session refresh” becomes “You are no longer signed out straight after resetting your password.”
- Write the Highlights last. Once you see the full list, pick the change with the most user impact.
- Add known issues and required actions. Ask QA and support what they know is still open.
- Review and publish. Have someone outside the team read it. If they ask “so what?” about an item, rewrite or cut it.
If your team ships every sprint, our guide to maintaining documentation in agile teams covers how to fit this into the release cycle without a last-minute scramble.
Draft Release Notes From Git Log
If your team writes commit messages in the Conventional Commits format (feat:, fix:, perf:, and ! for breaking changes), plain git gets you most of the way to a first draft. These are the exact commands we ran on the sample repository, which has tags v2.3.0, v2.4.0 and v3.0.0:
# 1. Find the tag before the release
git describe --tags --abbrev=0 v2.4.0^
# 2. List every change since that tag, oldest first
git log v2.3.0..v2.4.0 --no-merges --reverse --format="- %s (%h)"
# 3. Group by Conventional Commits type
for type in feat fix perf; do
echo "## $type"
git log v2.3.0..v2.4.0 --no-merges --format="- %s" --grep="^$type"
done
# 4. Find breaking changes (type! or type(scope)!)
git log v2.4.0..v3.0.0 --no-merges -E --grep='^[a-z]+(\([^)]+\))?!:' --format="- %s"And this is the output, unchanged:
v2.3.0
- feat(export): add CSV export for invoices (9f10b79)
- fix(auth): keep users signed in after a password reset (ab2d5e8)
- docs: update API rate limit table (2426bcf)
- feat(api): add GET /v2/invoices/{id}/pdf endpoint (6824663)
- fix(ui): stop the date picker closing on scroll (072cb5d)
- perf(search): cache filter counts (19d5800)
- feat(api): deprecate GET /v1/reports (b003e05)
## feat
- feat(api): deprecate GET /v1/reports
- feat(api): add GET /v2/invoices/{id}/pdf endpoint
- feat(export): add CSV export for invoices
## fix
- fix(ui): stop the date picker closing on scroll
- fix(auth): keep users signed in after a password reset
## perf
- perf(search): cache filter counts
- feat(api)!: remove GET /v1/reportsA few notes on how these work. git describe --tags --abbrev=0 v2.4.0^ finds the most recent tag before the release commit, which gives you the start of the range. A..B means “commits reachable from B but not from A”, so it covers exactly the work in that release. --format (unlike --pretty=format:) ends every entry with a newline, which keeps the lists clean. --grep matches the commit message; the -E flag turns on extended regular expressions for the breaking-change pattern. The git log documentation lists every placeholder you can use in --format.
The output is a raw list, not release notes. Compare it with the filled-in example above: the commit subjects became user-facing sentences, the docs commit disappeared, and the deprecation moved into its own section.
If you publish releases on GitHub, its release form also has a Generate release notes button that lists merged pull requests and contributors, and a .github/release.yml file can group pull requests by label (GitHub docs). We did not test that feature for this guide. Either way, treat the generated text as a draft and rewrite it for your readers.
Release Notes Best Practices
- Use the same headings every time. Regular readers learn to jump straight to Fixed or Breaking changes.
- Lead with the user benefit. “Export invoices to CSV” beats “Added CSV serializer to InvoiceService.”
- Be specific. Name the screen, endpoint or setting. Add a number when you measured one, and never invent one.
- Link out for detail. Keep each item to a sentence or two and link to the docs page or migration guide.
- Give deprecations a removal version and a replacement. Our guide to API versioning and deprecation notices covers the wording in detail.
- Keep the source in version control. Release notes written in Markdown next to the code get reviewed like code. See version control for documentation.
- Agree on tone once. Put rules such as tense, capitalisation and how to name features in your documentation style guide so every writer produces the same voice.
Release notes close the loop on planning documents too: the features in a release usually trace back to a product requirements document, and linking the two makes it easier for product and support teams to see what shipped against what was planned.
Conclusion
Release notes work when they are predictable and written for the reader. Use the template above with the same headings every release, start from the git log between your last two tags, cut what users will not notice, and rewrite the rest as plain-language outcomes. Give deprecations, breaking changes and required actions their own sections, and keep a full changelog in the repository for anyone who needs every detail.
FAQ
What should a release notes template include?
A title with the product name, version and date, a short Highlights section, and fixed sections for New, Improved, Fixed, Deprecated, Breaking changes, Known issues and Action required, plus links to the full changelog and docs.
What is the difference between release notes and a changelog?
A changelog is a complete technical record of notable changes, usually in CHANGELOG.md for developers. Release notes are a selective, plain-language summary of a release for users, focused on impact and what to do next.
How long should release notes be?
As short as the release allows. One or two sentences per item is enough when each one links to documentation for detail. A small patch release may need only a Fixed section.
Who writes release notes?
Often a technical writer or product manager, with input from engineering, QA and support. Developers usually provide the raw list through commit messages or pull request titles.
Can I generate release notes automatically?
You can generate a first draft from commit messages or merged pull requests, for example with git log or GitHub’s Generate release notes button. Review and rewrite that draft for users before publishing.
Should release notes mention known issues?
Yes. Listing known issues with any workaround builds trust and reduces support tickets, because users learn about the problem from you first.







