- PVSM.RU - https://www.pvsm.ru -
Привычный хаос в названиях коммитов. Знакомая картина?
Наверняка вы знаете git-flow [1]. Это отличный набор соглашений по упорядочиванию работы с ветками в Git. Он хорошо документирован и широко распространен. Обычно мы знакомы с правильным ветвлением и много говорим об этом, но, к сожалению, уделяем слишком мало внимания вопросу наименования коммитов, поэтому часто сообщения в Git пишутся бессистемно.
Меня зовут Ержан Ташбенбетов, я работаю в одной из команд Яндекс.Маркета. И сегодня я расскажу читателям Хабра, какие инструменты для создания осмысленных коммитов мы используем в команде. Приглашаю присоединиться к обсуждению этой темы.
Отсутствие договоренностей при наименования коммитов затрудняет работу с историей в Git. Такое было в нашей команде. До использования общего для всех регламента и внедрения автоматизации типичные коммиты выглядели следующим образом:
SECRETMRKT-700: пропали логотипы партнеров
Приложение падает, поправил.
SECRETMRKT-701, SECRETMRKT-702: Отцентрировал картинки на всех ...
Во-первых, каждый разработчик писал сообщения как хотел: кто-то описывал задачу, кто-то перечислял внесенные изменения, кто-то использовал генератор случайных фраз. Всё было вразнобой. Во-вторых, номера задач, присутствовавшие в коммитах, не только укорачивали полезный текст, но и не предоставляли ничего взамен. Это мешало эффективно работать с историей в Git.
По этой причине мы внедрили в команде стандарт Conventional Commits, стали генерировать коммиты в консольной утилите commitizen и проверять результат с помощью commitlint. В результате коммиты изменились и стали выглядит так:
refactor(tutorial): оптимизировать работу эпиков в тултипах
feat(products): добавить банер с новогодними скидками
fix(products): исправить в банере формат даты
Читать историю и распознавать внесенные изменения стало проще. Мы не отказались от указания номеров задач, всё аккуратно перенесено внутрь коммитов согласно конвенции Conventional Commits.
Дальше я расскажу, как добиться схожего порядка в Git.
Если попробовать разобраться в том, какие практики применяются в индустрии, то можно обнаружить следующие варианты:
Нам нужно больше порядка в коммитах!
Методология Conventional Commits [2] выделяется на фоне других стандартов и заслуживает пристального изучения по ряду причин:
Пример коммита по этому стандарту:
fix(products): поправить длину строки с ценой
Часть заголовков неправильно отображается в мобильной версии из-за ошибок
в проектировании универсальных компонентов.
МЕТА ДАННЫЕ: SECRETMRKT-578, SECRETMRKT-602
<type>(<scope>): <subject>
<body>
<footer>
build | Сборка проекта или изменения внешних зависимостей |
ci | Настройка CI и работа со скриптами |
docs | Обновление документации |
feat | Добавление нового функционала |
fix | Исправление ошибок |
perf | Изменения направленные на улучшение производительности |
refactor | Правки кода без исправления ошибок или добавления новых функций |
revert | Откат на предыдущие коммиты |
style | Правки по кодстайлу (табы, отступы, точки, запятые и т.д.) |
test | Добавление тестов |
Merge branch 'fix/SECRETMRKT-749-fix-typos-in-titles'
Стандарт коммитов Conventional Commits используют котрибьюторы lerna [5]
Нужно добавить автоматизации и удобства. Для решения этого вопроса нам потребуется два инструмента: генератор коммитов и линтер коммитов, настроенный на проверку перед пушем в репозиторий.
Этот инструмент позволяет генерировать коммиты при помощи встроенного визарда. Кроме того, commitizen хорошо поддерживается сообществом и, благодаря дополнительным модулям, отлично настраивается.
npm i -g commitizen
npm i -D cz-customizable
"use strict";
module.exports = {
// Добавим описание на русском языке ко всем типам
types: [
{
value: "build",
name: "build: Сборка проекта или изменения внешних зависимостей"
},
{ value: "ci", name: "ci: Настройка CI и работа со скриптами" },
{ value: "docs", name: "docs: Обновление документации" },
{ value: "feat", name: "feat: Добавление нового функционала" },
{ value: "fix", name: "fix: Исправление ошибок" },
{
value: "perf",
name: "perf: Изменения направленные на улучшение производительности"
},
{
value: "refactor",
name:
"refactor: Правки кода без исправления ошибок или добавления новых функций"
},
{ value: "revert", name: "revert: Откат на предыдущие коммиты" },
{
value: "style",
name:
"style: Правки по кодстайлу (табы, отступы, точки, запятые и т.д.)"
},
{ value: "test", name: "test: Добавление тестов" }
],
// Область. Она характеризует фрагмент кода, которую затронули изменения
scopes: [
{ name: "components" },
{ name: "tutorial" },
{ name: "catalog" },
{ name: "product" }
],
// Возможность задать спец ОБЛАСТЬ для определенного типа коммита (пример для 'fix')
/*
scopeOverrides: {
fix: [
{name: 'style'},
{name: 'e2eTest'},
{name: 'unitTest'}
]
},
*/
// Поменяем дефолтные вопросы
messages: {
type: "Какие изменения вы вносите?",
scope: "nВыберите ОБЛАСТЬ, которую вы изменили (опционально):",
// Спросим если allowCustomScopes в true
customScope: "Укажите свою ОБЛАСТЬ:",
subject: "Напишите КОРОТКОЕ описание в ПОВЕЛИТЕЛЬНОМ наклонении:n",
body:
'Напишите ПОДРОБНОЕ описание (опционально). Используйте "|" для новой строки:n',
breaking: "Список BREAKING CHANGES (опционально):n",
footer:
"Место для мета данных (тикетов, ссылок и остального). Например: SECRETMRKT-700, SECRETMRKT-800:n",
confirmCommit: "Вас устраивает получившийся коммит?"
},
// Разрешим собственную ОБЛАСТЬ
allowCustomScopes: true,
// Запрет на Breaking Changes
allowBreakingChanges: false,
// Префикс для нижнего колонтитула
footerPrefix: "МЕТА ДАННЫЕ:",
// limit subject length
subjectLimit: 72
};
{
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
},
"cz-customizable": {
"config": "config/git/commitizen.js"
}
},
}
git cz
Визард commitizen сначала соберет информацию о типе, области коммита, затем последовательно запросит текст, который будет в описании, в теле, в нижнем колонтитуле и после вашего согласия создаст коммит.
Обязательно посмотрите [8] на пример работы настроенной утилиты commitizen и подключенного к нему адаптера cz-cusomizable
npm i -D husky @commitlint/cli
{
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS -g './config/git/commitlint.js'"
}
},
"devDependencies": {
"@commitlint/cli": "^7.2.1",
"husky": "^1.1.3",
}
// Файл создан на основе @commitlint/config-conventional
module.exports = {
rules: {
// Тело коммита должно начинаться с пустой строки
"body-leading-blank": [2, "always"],
// Нижний колонтитул коммита должен начинаться с пустой строки
"footer-leading-blank": [2, "always"],
// Максимальная длина заголовка 72 символа
"header-max-length": [2, "always", 72],
// Область всегда только в нижнем регистре
"scope-case": [2, "always", "lower-case"],
// Описание не может быть пустым
"subject-empty": [2, "never"],
// Описание не должно заканчиваться '.'
"subject-full-stop": [2, "never", "."],
// Тип всегда только в нижнем регистре
"type-case": [2, "always", "lower-case"],
// Тип не может быть пустым
"type-empty": [2, "never"],
// Перечислим все возможные варианты коммитов
"type-enum": [
2,
"always",
[
"build",
"ci",
"docs",
"feat",
"fix",
"perf",
"refactor",
"revert",
"style",
"test"
]
]
}
};
Всё. Теперь все коммиты будут проверяться перед отправкой в репозиторий :)
Обязательно посмотрите [11] на пример работы настроенной утилиты commitlint
И то, и другое! В связке они приносят отличный результат: первый генерирует коммиты, второй их проверят.
Это крайне интересный вопрос. Коммит это изменение кода, сообщение в коммите можно расценивать как инструкцию по изменению этого кода. Сделать, изменить, добавить, обновить, поправить — всё это конкретные инструкции для разработчика.
Кстати, повелительное наклонение рекомендовано в самой системе версионирования Git [12]:
[[imperative-mood]]
Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
to do frotz", as if you are giving orders to the codebase to change
its behavior.
Стоит. В целом я заметил, что мы стали охотнее детализировать изменения, внесенные в кодовую базу. В теле коммита мы подробно расписываем почему пришлось использовать те или другие решения. Разбираться в истории стало объективно проще. Плюс наш продукт развивается, и мы ожидаем пополнения в команде. Уверен, что благодаря внедрению стандарта и автоматизации новичкам будет легче встроиться в процесс разработки.
Попробуйте и поделитесь результатом.
Автор: tashbenbetov
Источник [16]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/300953
Ссылки в тексте:
[1] git-flow: https://nvie.com/posts/a-successful-git-branching-model/
[2] Conventional Commits: https://www.conventionalcommits.org
[3] AngularJS: https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits
[4] yargs: https://github.com/yargs/yargs
[5] lerna: https://github.com/lerna/lerna
[6] commitizen: https://github.com/commitizen/cz-cli
[7] cz-customizable: https://github.com/leonardoanalista/cz-customizable
[8] посмотрите: https://asciinema.org/a/212473
[9] husky: https://github.com/typicode/husky
[10] commitlint: https://github.com/marionebl/commitlint
[11] посмотрите: https://asciinema.org/a/212490
[12] Git: https://git.kernel.org/pub/scm/git/git.git/tree/Documentation/SubmittingPatches
[13] Репозиторий: https://github.com/tashbenbetov/make-commit-messages-great-again
[14] Commitlint: https://marionebl.github.io/commitlint
[15] конфигуратор: https://commitlint.io
[16] Источник: https://habr.com/post/431432/?utm_campaign=431432
Нажмите здесь для печати.