Мы часто спешим закоммитить свои изменения в Git и в спешке пишем сообщения коммитов довольно рандомным образом. Я видел, что люди вставляют туда дату и время или даже пишут что-то типа commit 1, commit 2.
Это нехорошо. Сообщения коммитов должны быть полезными. В них должна быть смысловая нагрузка, чтобы люди, работающие над проектом и читающие код, могли прочесть сообщение и узнать, какие изменения были внесены тем или иным коммитом.
Давайте разберем простой способ решения этой проблемы.
Что такое Commitlint?
Commitlint — это простой инструмент для линтинга сообщений коммитов. Он следит за тем, чтобы ваши сообщения соответствовали установленному набору правил.
Commitlint запускается как husky pre-commit hook, то есть до коммита кода, и блокирует коммит в случае, если сообщение не проходит проверку.
Использование Commitlint в простом JavaScript-проекте
Давайте рассмотрим на примере, как настроить Commitlint в простом JavaScript-проекте. Для начала мы создадим пустой проект:
mkdir commitlint_example && cd commitlint_example npm init # OR yarn init # Just accept the defaults when prompted to configure the project
Теперь давайте инициализируем пустой Git-репозиторий:
git init
Мы также должны добавить файл .gitignore, чтобы некоторые файлы не входили в коммиты:
node_modules/
От редакции Techrocks. Рекомендуем статью «Как удалить конфиденциальный файл из истории коммитов на GitHub».
После этого добавляем файл index.js и выводим что-нибудь в консоль:
console.log("Hello, World!!!")
При запуске node . в вашем терминале должен выводиться текст:
Настройка Commitlint
Мы настроим Commitlint, следуя официальной документации по локальной настройке.
Для начала нам нужно установить CLI Commitlint (интерфейс командной строки) и добавить конфиг (в данном случае — конфиг дефолтного Соглашения о коммитах).
npm install @commitlint/cli @commitlint/config-conventional --save-dev # OR yarn add -D @commitlint/cli @commitlint/config-conventional
Добавим кое-какие настройки конфигурации в файле commitlint.config.js:
module.exports = { extends: [ "@commitlint/config-conventional" ], }
Теперь следует установить husky, чтобы запускать Commitlint как pre-commit hook.
npm install husky --save-dev # OR yarn add -D husky
Еще надо включить хуки husky:
npx husky install # OR yarn husky install
Мы можем добавить шаг prepare, чтобы включить хуки при установке:
npm set-script prepare "husky install"
С установкой husky покончено. Теперь нужно добавить pre-commit hook для запуска Commitlint перед коммитом кода.
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1" # OR yarn husky add .husky/commit-msg "yarn commitlint --edit $1"
Настройка Commitlint завершена. Давайте проверим, все ли работает.
Для начала добавим все файлы в стейджинг:
git add -A
Теперь попробуем сделать коммит изменений. При этом напишем сообщение коммита, не придерживаясь установленных правил:
git commit -m "set up a basic js project, added commitlint and husky for liniting commit messages"
Вы должны получить примерно такой результат (с ошибками). Если коммит пройдет успешно, скорее всего, вы где-то ошиблись в настройках. Проверьте, все ли указанные команды вы запустили и попробуйте отменить коммит, запустить скрипты и закоммитить изменения снова.
А теперь давайте сделаем коммит с правильным сообщением. Запустите следующую команду:
git commit -m "ci: initialised basic js project, added commitlint and husky to lint commit messages"
Теперь все прошло успешно.
Как работает дефолтное соглашение Commitlint
В качестве соглашения по умолчанию Commitlint использует Соглашение о коммитах. В соответствии с этим Соглашением, сообщения коммитов должны иметь следующую структуру:
<тип>[необязательный контекст]: <описание> [необязательное тело] [необязательная(ые) сноска(и)]
Например, если я исправил баг, имеющий отношение к UI, сообщение коммита может быть таким:
fix(ui): Button was not showing up properly on mobile view.
Здесь тип — это fix, т. е. исправление бага. В контексте указан скоуп — ui, поскольку исправление касается пользовательского интерфейса. В описании дается больше контекста относительно того, что именно исправлено.
Обратите внимание, что в контексте можно добавить не один скоуп. Например:
feat(ui,lang): added an option to save the image as svg and added language support for Spanish.
Здесь мы представили две фичи — новую кнопку для сохранения изображения в формате svg и поддержку испанского языка. Скоупы можно разделять тремя видами разделителей: запятыми, слэшами и обратными слэшами (, / \).
Маленькое замечание: нужно стараться делать коммиты маленькими и максимально специфичными. Могут быть исключения, но наш пример — не тот случай. Мы написали такое сообщение лишь чтобы показать два скоупа в контексте.
Серьезные изменения обычно обозначаются восклицательным знаком. Но вы также можете прямо написать BREAKING CHANGE в футере сообщения коммита. Хороший подход — и восклицательный знак ставить, и BREAKING CHANGE писать. Например:
refactor(runtime)!: Dropped support for NodeJS v12 BREAKING CHANGE: Support for NodeJS v12 has been dropped due to the latest refactor, please upgrade to the latest LTS version of No
Это подводит нас к многострочным сообщениям коммитов. Порой нам нужно дать больше контекста читателю, чтобы он сразу понял, что поменялось. В таком случае лучше всего включить нужную информацию в сообщение коммита. Например:
docs: Added an aria-label in the IconButton example aria-label is a required prop by the IconButton component. If it is not present, the build will fail
Преимущества использования Commitlint
- Автоматические логи изменений. Если коммиты соответствуют стандартному соглашению, инструменты вроде standard-version могут генерировать логи изменений автоматически. (От редакции Techrocks: см. «Что такое changelog проекта и как его создать»).
- Более понятные коммиты. Если в сообщении указан тип коммита и скоуп, читателю проще понять, что за изменения внесены этим коммитом.
- Соблюдение определенных правил. Когда у вас крупный проект, над которым работает много людей, трудно уследить за тем, чтобы все придерживались принятого соглашения и писали сообщения коммитов в одном стиле. Commitlint блокирует коммиты с сообщениями, не соответствующими правилам, и таким образом принудительно внедряет единообразие.
Итак, вы познакомились с основами использования Commitlint. Во второй части этой статьи мы погрузимся немного глубже и узнаем, как писать собственные правила и как запускать Commitlint CI в GitHub Actions.
Как создавать пользовательские правила Commitlint
Соглашение о коммитах подходит для большинства проектов. Но вы можете захотеть добавить какие-то правила, специфичные для вашего проекта.
Полную информацию на этот счет можно найти в документации.
Для примера мы возьмем приложение, в котором есть библиотека кнопок, созданная при помощи TailwindCSS. Вы можете добавить свое творение в это приложение при помощи пул-реквеста.
Коммиты здесь могут быть разных типов. Для примера мы возьмем тип button. Для этого мне потребуется перезаписать правило type-enum в Соглашении о коммитах.
Для этого я создам объект rules в моем конфиге Commitlint и внесу button как тип. Вот как должен выглядеть наш commitlint.config.js:
module.exports = { extends: [ "@commitlint/config-conventional" ], rules: { "type-enum": [2, "always", ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test", "button"]], } }
Я просто добавил тип button поверх типов, установленных по умолчанию.
Давайте это закоммитим:
git add -A git commit -m "ci(commitlint): added button as a type of commit"
Теперь протестируем наш тип button. Для примера я просто добавлю новую строку в файл index.js. Теперь он будет выглядеть так:
console.log("Hello, World!!!") console.log("New Button")
Давайте сделаем коммит:
git add -A git commit -m "button: added a new console.log to qualify as a button"
У вас должен получиться примерно такой же результат.
Как использовать Commitlint с GitHub Actions
Линтинг сообщений коммитов происходит локально. К сожалению, подобные проверки могут быть пропущены. Поэтому мы можем добавить еще один шаг в наш процесс CI/CD для повторной проверки.
В этом примере мы будем использовать GitHub Actions, но в документации есть официальные руководства также для Travis CI, Circle CI и GitLab CI.
Как запушить наш код на GitHub
Чтобы использовать GitHub Actions, нам сначала нужно сделать push нашего кода на GitHub. Давайте сделаем это по-быстрому.
Я воспользуюсь GitHub CLI, но вы можете делать через GUI. Главное — не забудьте добавить upstream в репозиторий.
Мы можем запушить код, запустив git push origin master
.
Как настроить Workflow
Для этого примера мы используем готовый GitHub Action, найти его можно здесь: https://github.com/wagoid/commitlint-github-action.
Нам нужно создать новую папку .github, а в ней — папку workflows. Затем мы создаем файл commitlint.yml и добавляем конфигурацию workflow.
.github/workflows/commitlint.yml
:
name: Lint Commit Messages on: [pull_request, push] jobs: commitlint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - uses: wagoid/commitlint-github-action@v4
Этот workflow будет запускаться при каждом пуше кода на GitHub и при каждом открытии пул-реквеста. Чтобы протестировать, сделаем коммит и пуш нашего кода.
git add -A git commit -m "ci(commitlint,workflow): added GitHub action workflow to run commitlint on push and pr" git push origin master
Теперь мы можем переместиться в GitHub-репозиторий, во вкладку actions, и там увидим наш workflow.
Я сделал опечатку в имени папки workflows, так что мне пришлось внести исправление и заново сделать коммит и пуш, так что имя коммита отличается.
Просматривая подробности, вы можете видеть, что workflow был успешен, поскольку все коммиты пока соответствовали соглашению.
Мы можем также посмотреть логи:
Теперь, когда вы настроили Commitlint, будет хорошей идеей добавить автоматизированные логи изменений. Зайдите в репозиторий standard version и попытайтесь реализовать это самостоятельно!
Перевод статьи «How to Write Good Commit Messages with Commitlint».
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]