Почему сообщения важны?
Сообщения коммита — это часть совместной работы, которую мы выполняем изо дня в день в команде, они работают как запись того, что произошло.
Каждый раз, когда вы выполняете коммит, вы записываете снимок вашего проекта, к которому вы можете вернуться или сравнить с ним позже.
— Книга Pro Git
Сообщения о фиксации используются по-разному, в том числе:
- Чтобы помочь будущему читателю быстро понять, что изменилось и почему это изменилось
- Чтобы помочь легко отменить определенные изменения
- Для подготовки примечаний к изменениям или версий для релиза.
Все три этих случая требуют чистого и последовательного стиля сообщений о фиксации.
Простые сообщения о фиксации с помощью Commitizen
Цель этого инструмента — определить стандартный способ фиксации правил и их передачи. Причина этого в том, что его легче читать, и он заставляет писать описательные коммиты. Устранение двусмысленности опций и умственной нагрузки при следовании стандарту вручную.
Commitizen задаст вам ряд вопросов, которые сгенерируют окончательное сообщение о фиксации. У него есть несколько адаптеров, в моем случае я предпочитаю контролировать вопросы, поэтому я использую расширение cz-format-extension.
Вы можете добавить commitizen в свой проект с помощью следующей командной строки
npm install commitizen --save-dev # npm
yarn add commitizen -D # Yarn
Добавьте любой из доступных адаптеров, в моем случае cz-format-extension:
npm install cz-format-extension --save-dev # npm
yarn add cz-format-extension -D # Yarn
В вашем package.json
вам нужно будет добавить следующий раздел:
...
"config": {
...
"commitizen": {
"path": "cz-format-extension"
}
}
...
Расширение Adapter cz-format-extension обеспечивает большую гибкость, поскольку вопросы могут быть определены в файле .czfrec.js
. Пример:
const { contributors } = require('./package.json')
module.exports = {
questions({inquirer}) {
return [
{
type: "list",
name: "type",
message: "'What is the type of this change:",
choices: [
{
type: "list",
name: "type",
message: "'What is the type of this change:",
choices: [
{
"name": "feat: A new feature",
"value": "feat"
},
{
"name": "fix: A bug fix",
"value": "fix"
},
{
"name": "docs: Documentation only changes",
"value": "docs"
},
...
]
},
{
type: 'list',
name: 'scope',
message: 'What is the scope of this change:',
choices: [
{
"name": "core: base system of the application",
"value": "core"
},
{
"name": "extensions: systems that are observed",
"value": "extensions"
},
{
"name": "tools: other things in the project",
"value": "tools"
},
]
},
{
type: 'input',
name: 'message',
message: "Write a short, imperative tense description of the changen",
validate: (message) => message.length === 0 ? 'message is required' : true
},
{
type: 'input',
name: 'body',
message: 'Provide a longer description of the change: (press enter to skip)n',
},
{
type: 'confirm',
name: 'isBreaking',
message: 'Are there any breaking changes?',
default: false
},
{
type: 'input',
name: 'breaking',
message: 'Describe the breaking changes:n',
when: answers => answers.isBreaking
},
{
type: 'confirm',
name: 'isIssueAffected',
message: 'Does this change affect any open issues?',
default: false
},
{
type: 'input',
name: 'issues',
message: 'Add issue references:n',
when: answers => answers.isIssueAffected,
default: undefined,
validate: (issues) => issues.length === 0 ? 'issues is required' : true
},
{
type: 'checkbox',
name: 'coauthors',
message: 'Select Co-Authors if any:',
choices: contributors.map(contributor => ({
name: contributor.name,
value: `Co-authored-by: ${contributor.name} <${contributor.email}>`,
}))
},
]
},
commitMessage({answers}) {
const scope = answers.scope ? `(${answers.scope})` : '';
const head = `${answers.type}${scope}: ${answers.message}`;
const body = answers.body ? answers.body : '';
const breaking = answers.breaking ? `BREAKING CHANGE: ${answers.breaking}` : '';
const issues = answers.issues ? answers.issues : '';
const coauthors = answers.coauthors.join('n');
return [head, body, breaking, issues, coauthors].join('nn').trim()
}
}
Файл создает процесс вопросов для:
- тип: соответствие спецификации семантического сообщения о выходе
- область применения: затронутая часть приложения
- сообщение: императивное письменное сообщение
- тело: более длинное описание
- нарушение: определить, является ли это изменение нарушением для семантического релиза.
- проблема: связанная проблема нашей системы тикетинга
- Соавторы: люди, работающие над задачами во время парного программирования
Все эти вопросы задаются интерактивно, а не с помощью мозговых усилий при выполнении ручной работы.
А затем вы можете добавить несколько красивых npm-скриптов в ваш файл package.json
, указывающих на локальную версию Commitizen:
...
"scripts": {
"commit": "cz"
}
Это будет более удобно для ваших пользователей, потому что тогда, если они захотят сделать коммит, всё, что им нужно будет сделать, это выполнить npm run commit
и они получат подсказки, необходимые для запуска коммита!
ПРИМЕЧАНИЕ: Если вы используете
precommit
хуки благодаря чему-то вродеhusky
, вам нужно будет назвать свой скрипт как-то иначе, чем"commit"
(например,"cm": "cz"
). Причина в том, что у npm scripts есть «функция», которая автоматически запускает скрипты с именем prexxx, где xxx — это имя другого скрипта. По сути, npm и husky будут запускать скрипты"precommit"
дважды, если вы назовете скрипт"commit"
, и обходной путь состоит в том, чтобы предотвратить npm-триггерный скрипт precommit.
Вот и все 🙂 . Отдельно упомяну commitlint, который является очень полезным инструментом для линтирования сообщений о коммитах. Я больше не использую его, так как он частично дублирует commitizen.