A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project. A good changelog gives you a detailed view into the development process and makes it easier for users and contributors to see precisely what notable changes have been made between each release (or version) of the package. Whereas the README is designed for new users, the changelog is designed to for existing users.
The changelog should contain an entry for every single version release of the package and contain the following information:
Using commit log diffs as changelogs is a bad idea: they’re full of noise. Things like merge commits, commits with obscure titles, documentation changes, etc. The purpose of a commit is to document a step in the evolution of the source code. Some projects clean up commits, some don’t. The purpose of a changelog entry is to document the noteworthy difference, often across multiple commits, to communicate them clearly to end users.
When people upgrade from one version to another, it should be painfully clear when something will break. If you do nothing else, list deprecations, removals, and any breaking changes in your changelog. For other developers, it should be very clear to upgrade to a version that lists deprecations, remove what’s deprecated, then upgrade to the version where the deprecations become removals.
The changelog is typically contained in a file named CHANGELOG
, NEWS
, RELEASES
, or HISTORY
and is most commonly a .md
or .rst
file. We recommend you use CHANGELOG.md
for packages and NEWS.md
for since this is common convention.
The template you used to create your first package alread includes a changelog (CHANGELOG.md
for Python and NEWS.md
for R. However, in R you can use usethis::use_news_md()
to automatically create a NEWS.md
file if ones does not already exist.
The changelog should be written in a manner that makes it easy to see certain types of changes made. It should be in reverse chronological order meaning the latest version comes first and the release version and date should be displayed. It is common to keep an Unreleased
section at the top to track upcoming changes until you have determined the appropriate version bump. How you capture the important changes in the version can vary but the below is a good approach where you use common headings to capture types of changes:
Added
Changed
Deprecated
Removed
Fixed
Refactor
If an item is related to an issue in GitHub, include the issue number in parentheses, e.g. (#10). If an item is related to a pull request, include the pull request number and the author, e.g. (#101, @bradleyboehmke). Doing this makes it easy to navigate to the relevant issues on GitHub.
Example:
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased
### Added
- Feature `xxx`: allows you to do some great stuff. <Provide good summary and you can even supply examples>.
- Feature `xxx`: allows you do this other great stuff.
### Removed
- Feature `xxx`: version 1.0.0 deprecated feature `xxx` has been removed.
- Param `xxx`: version 1.0.0 deprecated param `xxx` has been removed.
### Fixed
- Bug in `xxx`: was throwing `xxxx` error when doing <provide good summary> (#87).
- Bug in `xxx`: was returning a integer instead of a float when <summary> (#86).
## Version 1.0.0
### Added
- Feature `xxx`: allows you to ... <summary>.
- Param `xxx`: added to feature `xyz` to allow for... <summary>.
### Deprecated
- Feature `xxx`: deprecated in favor of feature `xxx` (#98, @johndoe).
- Param `xxx`: deprecated in favor of param `xxx` (#97, @janedoe).
## Version 0.9.1
### Fixed
- Bug in xxx: <summary> (#74).
- Bug in xxx: <summary> (#73).
- Bug in xxx: <summary> (#72).
## Version ...
...
Both the and package templates include a changelog file.