Generating changelog automatically with Standard Version

Git JavaScript

The creation of software usually takes place across multiple iterations, and our code changes often. Because of that, we need a way to describe this process with the use of versions.

There are quite a few ways to do that. Recently the most widely adopted approach seems to be semantic versioning. It involves a sequence of three digits separated with dots.

  • Major version
    Increasing the major version number means that we introduced a breaking change. Our users might probably need to alter their code to adapt to it
  • Minor version
    Bumping the minor version number indicates that we introduce a feature that adds functionality in a backward-compatible way
  • Patch version
    If our new release increases just the patch version number means introducing a backward-compatible bug fix

If you want to know more about how to deal with Semantic Versioning in your package.json file, check out Keeping your dependencies in order when using NPM

When our codebase evolves, it might be challenging to track all of the changes accurately.  Fortunately, we have tools that help us do just that.

Using Conventional Commits

The Standard Version utility can figure out a proper release version and generate a changelog file for us. To do that, we need to follow a Conventional Commits specification.

The Conventional Commits provides a way for us to mark our changes as new features or fixes. Therefore, Standard Version can infer the version based on that and generate a changelog.

The “fix” type indicates that this commit removes a bug in the codebase. Creating a release with such a commit results in bumping the patch version

Creating a “feat” commit means introducing a new feature. Therefore, it increases the minor version.

A commit marked as a breaking change results in increasing the major version. We can create it either by appending the    sign, or adding the information in the footer.

We can use many different types of commits, such as:

  • test – when modifying existing tests, or adding new ones
  • refactor – changing the code in a way that does not fix a bug nor adds features
  • docs – modifying the documentation
  • chore – routine tasks such as updating dependencies
  • build – affecting the way the application builds

We can make any of the above commits more precise by adding a scope.

Even without the benefits such as generating the changelog and dealing with the semantic versioning, using the above convention make our commits more explicit and meaningful.

Introducing Standard Version

Thanks to using the Conventional Commits, we can now start using the Standard Version.

Now, we need to add it to our   in  .

When we create the first release, we might want to pass some additional parameters.

✖ skip version bump on first release
✔ created
✔ outputting changes to
✔ committing
✔ tagging release v1.0.0
ℹ Run git push --follow-tags origin master to publish

A few important things are happening above. The most noticeable is the fact that we now have a CHANGELOG file. Since my initial commit was a  , it does not mention any features.

Because we’ve used the   flag, our version in the   hasn’t changed.

The thing we need to look deeper now are the Git tags.

Working with Tags

In this part of the Getting geeky with Git series, we learn that both branches and tags refer to a specific commit. With tagging, we can point to a specific point in the repository’s history. A common use-case for tags is versioning.

When we run  , Standard Version creates a new tag for us. We can list all of our tags with  :

v1.0.0 chore(release): 1.0.0

We can also see here that Standard Version automatically committed all of the changes to the changelog.

The Standard Version suggests that we now run  . This pushes all of our changes along with the tags.

When Standard Version runs, it figures out the changelog and the version by comparing the changes with the latest tag version on your local repository. If you don’t have the latest tags fetched, you might run into unexpected results when generating the changelog. I’ve bumped into this issue in the past.

To make sure that you have all of the tags fetched, you can run  .

Making further changes

Now let’s make some additional changes, and let’s see how the Standard Version works.

fix: prevent the application from crashing

Doing the above adds the following to the changelog:

Above, we can see that the patch version is bumped because we only committed a bug fix. Now, let’s add a feature.

feat: add the possibility to filter posts

chore(gitignore): add node_modules

We can notice that only relevant information is added, and the   gets omitted. Now, let’s add some breaking changes.

feat(Posts): add pagination to the posts endpoint
BREAKING CHANGE: now the result might not contain all posts

fix(Posts)!: change the way that the posts are filtered to deal with a bug

This time Standard Version bumps the major number because of breaking changes.

We can also view all of our tags on GitHub, for example.


In this article, we’ve learned how to use Standard Version to generate a changelog and deal with the versioning. To do so, we’ve learned about the Conventional Commits. We’ve also briefly got to know what purpose tags serve in Git. All of that can help us to make our repository cleaner and let the Standard Version library do the heavy lifting.

Notify of
Inline Feedbacks
View all comments