I’m participating in nuggets Creators Camp # 4, click here to learn more and learn together!

preface

Recently, I was working on the front-end engineering of monorepo project, one part of which was related to Git commit. Therefore, I referred to several projects, summarized the relevant tool chain, and wrote an article.

The whole tool chain revolves around the generation, verification, and finally changelog generation of Git Commit message

Here are some of the tools used by the libraries I surveyed in this process:

tdesign-vue-next-starter ant-design-vue vue vite
Commit specification Presents the specification Presents the specification An extension specification based on the Angular specification An extension specification based on the Angular specification
Generate a commit message commitizen x x x
Check the commit message commitlint commitlint Use custom scripts for verification Use custom scripts for verification
Generate the changelog x Custom scripts conventional-changelog conventional-changelog

In addition to some customized tools in the project, I mainly used the following open source tools:

  • Commitizen: Generates a commit message
  • Commitlint: verifies the COMMIT Message
  • Convention-changelog: generates changelog

Before we introduce these tools, let’s take a look at the commit specification that is most commonly used today

Presents the commit specification

There are a lot of articles on the net, we should also be very familiar with, do not understand the article can see Ruan Yifeng. The content of this section is derived from this article, and I will list some important points here

The Commit message consists of three parts: Header, Body, and Footer.

<type> (the < scope >) : < subject > / / short line < body > / / short line < footer >Copy the code

The Header is required, and the Body and Footer can be omitted.

Header types include the following seven types:

  • Feat: New Feature
  • Fix: Fixes bugs
  • -Jenny: There are some docs.
  • Style: format (changes that do not affect code execution)
  • Refactor: refactoring (i.e. code changes that are not new features or bug fixes)
  • Test: Adds a test
  • Chore: Changes to the build process or helper
  • Pref: Code changes that improve performance

The Body section is a detailed description of the commit, broken into multiple lines.

The Footer section is only used in two cases:

  • Incompatible variationIn order toBREAKING CHANGEAt the beginning, it is followed by a description of the change, along with the reasons for the change and the method of migration
  • Close the Issue

To rollback git commit, the commit message must begin with revert:.

revert: feat(pencil): add 'graphiteWidth' option

This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
Copy the code

Commit tool chain

  • Commitizen: Generates a commit message
  • Commitlint: verifies the COMMIT Message
  • Convention-changelog: generates changelog

These tools, they have different functions, so how do you link the flow of these tools together? Let’s start with git commit’s periodic hooks

Git hooks: Git hooks

  • pre-commitHook: Runs before submission information is typed and can be usedeslintWait for Linter’s code verification and repair
  • prepare-commit-msgHook: Runs before starting the Commit Message editor. You can generate a Commit Message at this stage (where commitizen is running) so that you don’t open the editor and type a Commit message
  • commit-msgHook: Fill in commit message and run ifGit abandons the commit if the hook script exits with a non-zero value. This can be used to verify that the Commit Message complies with the specification. (Commitlint runs at this stage)
  • post-commitHook: Git commit executes after the commit process is complete

Changelog generation is not in git hooks, because it is not required for every commit, just before a new release

commitizen

Generate a Git commit message using the command line interface

Before using Commitizen, we first need to tell Commitizen which COMMIT specification we are using, so we can do the following configuration:

  1. Install dependencies, assuming we usecz-conventional-changelogAs a configuration, more configurations can be viewedhere
npm install commitizen cz-conventional-changelog --save
Copy the code
  1. In package.json, addcommitizenThe configuration of the
{
  "script": {"cz": "cz"
  }
  "config": {
    "commitizen": {
      "path": "cz-conventional-changelog"}}}Copy the code

So commitizen knows what specification we’re using

  1. Generate a COMMIT message and commit commit:
npx cz

#The result is as follows:
? Select the type of change that you are committing: feat:     A new feature
? What is the scope of this change (e.g. component or file name): (press enter to skip)

? Write a short, imperative tense description of the change (max 94 chars): test
? Provide a longer description of the change: (press enter to skip)

? Are there any breaking changes? No
? Does this change affect any open issues? No

## commit Message: feat
Copy the code

The content of command line interaction is derived from the CONFIGURATION of CZ-Xconventional – Changelog. Different COMMIT specifications have different command line interaction

The command line interaction diagram is as follows:

How does it work with Git hooks?

Configure the git hook for prepare-commit-msg

# .git/hook/prepare-commit-msg
exec < /dev/tty && node_modules/.bin/cz --hook || true
Copy the code

At git-commit time, cz is executed to interactively generate commit information on the command line

  • Exec < /dev/tty, git hooks are not interactive by default. This command allows users to use their terminals to interact with Commizen during the hook.

  • Cz generates a commit message and commits the git hook. Cz generates a commit message and commits the git hook. Pass git commit command)

commitlint

Like ESLint, commitLint normalizes validation of commit messages.

Likewise, commitLint needs a configuration that tells it which specification we need to use. You can configure commitlint as follows:

// Create configuration files in the project root directory
// commitlint.config.js
module.exports = { extends: ['@commitlint/config-conventional']};Copy the code

Here is the @commitlint/ config-Conventional configuration. For other configurations, please check the official documentation.

Commitlint must be used with git hooks and validation must be performed after git commit information is generated/filled in. Therefore, the git hook used is commit-msg

# .git/hooks/pre-commit
npx commitlint -e $1
Copy the code
  • The $1, the first argument of the command line is passed incommit-msgGit hooks in the.git/COMMIT_EDITMSG, the fileStores the message text for the commit
  • Commitlint-e File path: Reads the Git commit message text from the file

Git hook synchronization

Our Git commit hooks are written in the.git/hooks directory and are run when you run git commit

However, git client hooks are not committed to git repositories, which means that when someone clone the repository, the hooks are not copied

To address this pain point, we need to synchronize our Git hooks with a few helper tools, including husky and simle-Git-hooks

Using simple-git-hooks as an example, here is how to configure this function:

  1. Install dependencies
npm install simple-git-hooks --save-dev
Copy the code
  1. Configuration package. Json
{
  "simple-git-hooks": {
    "pre-commit": "npx lint-staged"."prepare-commit-msg": "exec < /dev/tty && node_modules/.bin/cz --hook || true"."commit-msg": "npx commitlint -e $1",}}Copy the code
  1. Run the command manually to install the hook to.git/hooks
npx simple-git-hooks
Copy the code

Since package.json is uploaded to the Git repository, these hook configurations are also saved, and once you clone the repository, you simply install the hooks.

Changelog generation

The xcomm-Changelog is used to generate changelog. You only need to run the following command to generate the Changlog file

conventional-changelog -p angular -i CHANGELOG.md -s
Copy the code
  • -p: The Angular commit specification
  • -i: Selects the input file
  • -s: The input file is the same as the output file

This command will add the latest version of CHANGELOG to the top of Changelog. md and will not modify the previous version of CHANGELOG

A single piece of changelog is a single Git commit message. Here is a changelog example (from @vitejs/plugin-vue) :

Generates the basic flow of Changelog

  1. Split all commit messages based on git tags, which start with v, such as v1.9.3 and v1.9.2.

  2. Filter out the COMMIT to generate Changelog.

    • Not all types of messages generate ChangelogIn the Angular specification, onlyfeat,fix,pref, as well asrevertThe rollback COMMIT is generated in Changelog. Other types need to be added. It is not recommended to putdocs,chore,style,,refactor,testJoin the changelog
  3. Based on the filtered Commit message, the latest tag version of Changelog is generated

    • Due to theYou can manually modify the Changelog file, soBy default, only the changelog with the most recent tag is generated, so parameters are needed-i, pass in the last Changelog file, and at the top of it, concatenate the newly generated Changelog

How does the Monorepo project generate Changelog?

Since there are multiple package packages in monorepo project, their Changelog needs to be separated separately.

However, according to the above generation method of Changelog, all the commit will be read and generated, without filtering the commit (excluding the commit that does not belong to this package).

Therefore, we need another parameter –commit-path:

Conventional -Changelog -p angular-i Changelog. md-s --commit-path < replace package directory >Copy the code

This tells xconvention-Changelog that every git commit file needs to be checked when changelog is generated. If the changed file is in the commit-path directory, The COMMIT is considered a valid COMMIT and is used to generate Changelog

The figure above shows how a commit is filtered through –commit-path. Because the packages of A and B are modified in the last commit, both A and B will have the commit information when they generate Changelog

conclusion

The commit tool chain has been introduced, and each tool has its own role to play, so you can choose whether or not to use these tools based on your own needs.

For example, tDesign-vue-next-starter is just a business template, not a tool library, and you don’t need Changelog (but you can).

Vite, Vue, etc., do not use Commitizen to generate a Commit message, because writing a Commit message might be more convenient (personally, I think it is more convenient), so it is not necessary.

Commit validation is done with commitLint and commitLint scripts. Vue and Vite extend the Angular specification, so validation scripts are also written by commitLint. You can also implement commitlint, which is probably not done for time reasons and is not of that high priority.

In fact, we don’t have to copy all of this, it’s more about understanding the process. For their own development of the project, only need to combine with their own needs.

If this article is of any help to you, please give me a thumbs-up 👍. Your encouragement is the biggest power on my way of creation