Your changelog is read by one kind of person: a buyer with your script already running, deciding whether to update. Write it for them.
Say what breaks, first
If an update changes a config key, a database column or a function signature, that goes at the top in bold, not buried under six bug fixes. A buyer who upgrades and finds their customisation gone will not be gentle about it in the reviews.
Group by what it means, not by commit
"Fixed null check in OrderService" means nothing to them. "Orders with no shipping address no longer throw an error at checkout" means something. Same fix, one is useful.
A shape that works
- Breaking: anything requiring action from them
- Added: new features they may want
- Fixed: bugs, described by symptom
- Updated: dependency and compatibility changes
Leave out empty sections rather than writing "none".
Version numbers people can reason about
Semantic versioning is worth following even loosely. Third number for fixes, second for new features, first for anything that breaks. A buyer seeing 2.0.0 knows to read carefully. A buyer seeing 1.4.3 knows they can probably just update.
Date every entry
Buyers use dates to judge whether an item is maintained. An undated changelog with ten entries could be from last month or from 2021, and they will assume the worse of the two.
Related: shipping updates without breaking your buyers' installs.