Customizing Commit Messages
Changesets supports configuring commit
to automatically submit the current changes when running the change
and bump
commands.
The default commit
information is provided by @changesets/cli/commit
, and the default information format is:
When the default commit information cannot meet the requirements, custom commit information is supported.
Customizing Commit Message Content
Commit information is divided into two types:
- Commit information automatically generated when running the
change
command.
- Commit information automatically generated when running the
bump
command.
The custom logic mainly implements two functions, getAddMessage
and getVersionMessage
, which are used to define the above two types of information, respectively.
getAddMessage
Params
The current changeset information created.
type Release = {
name: string;
type: VersionType;
};
type Changeset = {
summary: string;
releases: Array<Release>;
};
Configuration information when committing.
When the commit configuration is an array, the second parameter supports passing in default configuration information, which will be used to pass this parameter.
Returns
Commit message content.
Default Implementation
The default processing logic of @changesets/cli/commit
is to start with docs(changeset):
, and the commit information is the summary
of the changeset, and [skip ci] information is added according to the skipCI
parameter configuration passed in.
type SkipCI = boolean | 'add' | 'version';
const getAddMessage = async (
changeset: Changeset,
options: { skipCI?: SkipCI } | null,
) => {
const skipCI = options?.skipCI === 'add' || options?.skipCI === true;
return outdent`docs(changeset): ${changeset.summary}${
skipCI ? `\n\n[skip ci]\n` : ''
}`;
};
outdent is used to remove the leading whitespace content of the template string to make the commit information more compliant with the specification.
getVersionMessage
Params
type VersionType = 'major' | 'minor' | 'patch' | 'none';
type Release = {
name: string;
type: VersionType;
};
type Changeset = {
id: string;
summary: string;
releases: Array<Release>;
};
type ComprehensiveRelease = {
name: string;
type: VersionType;
oldVersion: string;
newVersion: string;
changesets: string[];
};
type PreState = {
mode: 'pre' | 'exit'; // Current state of pre mode
tag: string; // Type of pre
initialVersions: {
[pkgName: string]: string; // Package name and version information before version upgrade
};
changesets: string[]; // List of changeset ids for this upgrade
};
type ReleasePlan = {
changesets: Changeset[]; // List of changesets for this upgrade
releases: ComprehensiveRelease[]; // Information of the current upgrade, including package name, current version, upgraded version, and upgrade type
preState: PreState | undefined; // If it is a pre-release, provide relevant state information
};
Configuration information when committing.
When the commit configuration is an array, the second parameter supports passing in default configuration information, which will be used to pass this parameter.
Returns
Commit message content.
Default Implementation
The default processing logic of @changesets/cli/commit
is to first display the number of packages that need to be released, then display the names and new version of the released packages, and [skip ci] information is added according to the skipCI
parameter configuration passed in.
const getVersionMessage = async (
releasePlan: ReleasePlan,
options: { skipCI?: SkipCI } | null,
) => {
const skipCI = options?.skipCI === 'version' || options?.skipCI === true;
const publishableReleases = releasePlan.releases.filter(
release => release.type !== 'none',
);
const numPackagesReleased = publishableReleases.length;
const releasesLines = publishableReleases
.map(release => ` ${release.name}@${release.newVersion}`)
.join('\n');
return outdent`
RELEASING: Releasing ${numPackagesReleased} package(s)
Releases:
${releasesLines}
${skipCI ? `\n[skip ci]\n` : ''}
`;
};
Configuration
The commit
field in the changesets configuration file is used to mark whether to submit commit information when running the change
and bump
commands, and the way to obtain commit information.
This configuration can be a boolean
. When it is true
, the default @changesets/cli/commit
formatting commit information will be used.
This configuration can be a string, directly declaring the module name or path of the commit information acquisition module.
This configuration also supports configuring arrays. The first element in the array is the module name or path of the commit information acquisition module, and the second element is the parameter value passed to the corresponding function, which will be passed as the second parameter of the getAddMessage
and getVersionMessage
functions.
Configuring Relative Paths
If the commit configuration is a relative path, it is a relative path under the .changesets
directory.
For example, create the .changeset/my-commit-config.js
file and define the following content:
.changeset/my-commit-config.js
async function getAddMessage(changeset, options) {}
async function getVersionMessage(releasePlan, options) {}
module.exports = {
getAddMessage,
getVersionMessage,
};
Configure commit
as ./my-commit-config.js
:
.changesets/config.json
{
"changelog": "./my-commit-config.js",
...
}
Using Modern.js Module
Customizing commit can also be managed using the Modern.js Module to provide a common solution.
Use npx @modern-js/create@latest
to create a mModern.js Module
? Please select the type of project you want to create: Npm Module
? Please fill in the project name: custom-commit
? Please select the programming language: TS
? Please select the package manager: pnpm
Implement Custom Content
src/index.ts
export async function getAddMessage() {}
export async function getVersionMessage() {}
Publish the module to NPM
Install the corresponding module in the root directory of the target repository, such as custom-commit
Configure the commit configuration of changesets as the package name
package.json
{
"commit": "custom-commit",
...
}
Using Monorepo Sub-Project
If your current repository is Monorepo, you can directly manage it using NPM module sub-projects.
Run pnpm run new
to create a module sub-project
? Please select the type of project you want to create: Npm Module
? Please fill in the sub-project name: custom-commit
? Please fill in the sub-project directory name: custom-commit
? Please select the programming language: TS
Implement Custom Content
src/index.ts
export async function getAddMessage() {}
export async function getVersionMessage() {}
Add the sub-project module dependency, such as custom-commit
, to the Monorepo root directory
package.json
{
"devDependencies": {
"custom-commit": "workspace:*",
...
}
}
Configure the commit configuration of Changesets as the package name
.changesets/config.json
{
"commit": "custom-commit",
...
}
After the module is published to NPM, it can still be used like a module type for other repositories.