Соглашение о коммитах

Простое соглашение о том, как нужно писать сообщения коммитов

Conventional Commits 1.0.0-beta.4

Главное

Conventional Commits - это простое соглашение о том, как нужно писать сообщения commit’ов. Оно описывает простой набор правил для создания понятной истории commit’ов, а также позволяет проще разрабатывать инструменты автоматизации, основанные на истории commit’ов. Данное соглашение совместимо с SemVer, описывая новые функции (features), исправления (fixes) и изменения, нарушающие обратную совместимость (breaking changes) в сообщениях commit’ов.

Сообщения commit’ов должны быть следующей структуры:


<type>[optional scope]: <description>

[optional body]

[optional footer]

Commit’ы могут содержать следующие структурные элементы для сообщений пользователям вашей библиотеки:

  1. fix: commit типа fix исправляет ошибку (bug) в вашем коде (он соответствует PATCH в SemVer)
  2. feat: commit типа feat добавляет новую функцию (feature) в ваш код (он соответствует MINOR в SemVer).
  3. BREAKING CHANGE: commit, который содержит текст BREAKING CHANGE: в начале своего не обязательного тела сообщения (body) или в подвале (footer), добавляет изменения, нарушающие обратную совместимость вашего API (он соответствует MAJOR в SemVer). BREAKING CHANGE может быть частью commit’а любого типа.
  4. Другое: commit’ы с типами, которые отличаются от fix: и feat:, также разрешены. Например, @commitlint/config-conventional (основанный на The Angular convention) рекомендует: chore:, docs:, style:, refactor:, perf:, test:, и другие.

Мы также рекомендуем improvement для commit’ов, которые вносят улучшения в текущую реализацию без добавления новых функций и исправления ошибок. Обратите внимание, что данный тип не описывается данной спецификацией и не имеет эффекта в SemVer (за исключением, когда он включает BREAKING CHANGE). Контекст (scope) может быть объявлен рядом с типом commit’а для добавления дополнительной информации о контексте. Он должен содержаться в круглых скобках, например, feat(parser): add ability to parse arrays.

Примеры

Сообщение commit’а с описанием и изменениям, нарушающим обратную совместимость, в теле

feat: allow provided config object to extend other configs

BREAKING CHANGE: `extends` key in config file is now used for extending other config files

Сообщение commit’a с не обязательным !, для того, чтобы привлечь внимание к изменениям, нарушающим обратную совместимость

chore!: drop Node 6 from testing matrix

BREAKING CHANGE: dropping Node 6 which hits end of life in April

Сообщение commit’а без тела

docs: correct spelling of CHANGELOG

Сообщение commit’а с указанием контекста (scope)

feat(lang): add polish language

Сообщение commit’а, исправляющего ошибку (fix), использующее не обязательный номер задачи (issue) в багтрекере

fix: correct minor typos in code

see the issue for details on the typos fixed

closes issue #12

Спецификация

Слова “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, и “OPTIONAL” в данном документе должны интерпретироваться как в RFC 2119.

  1. Commit’ы должны (MUST) начинаться с типа, который является существительным: feat, fix, и т.д., за которым следуют не обязательное (OPTIONAL) указание контекста (scope), двоеточие и пробел.
  2. Тип feat должен (MUST) использоваться, когда commit добавляет новый функционал (feature) в ваше приложение или библиотеку.
  3. Тип fix должен (MUST) использоваться, когда commit исправляет ошибку (fix) в вашем приложении или библиотеке.
  4. Контекст (scope) может (MAY) следовать после типа. Контекст должен (MUST) быть существительным, заключенным в круглые скобки, описывающий часть кодовой базы, которую затронул commit. Например, fix(parser):.
  5. Описание должно (MUST) следовать через пробел сразу же после типа/контекста. Описание - это краткая выжимка об изменениях кода, например, fix: array parsing issue when multiple spaces were contained in string.
  6. Тело (body) commit’а может (MAY) следовать после короткого описания, добавляя дополнительную информацию об изменениях в коде. Тело должно (MUST) отделяться от короткого описания одной пустой строкой.
  7. Подвал (footer) может (MAY) быть представлен одной или несколькими строками после тела commit’а. Он должен быть отделен от тела commit’а одной пустой строкой. Подвал должен (MUST) содержать мета-информацию о commit’е. Например, связанные pull-request’ы, обсуждения, изменения, нарушающие обратную совместимость. По одной мета-информации на строку.
  8. Изменения, нарушающие обратную совместимость (breaking changes), должны (MUST) быть указаны в самом начале тела (body) или в начале одной из строк подвала (footer). Изменения, нарушающие обратную совместимость, должны (MUST) начинаться с текста, написанного прописными буквами, BREAKING CHANGE, за которым должны следовать двоеточие и пробел.
  9. Описание изменений, нарушающих обратную совместимость, должно (MUST) следовать после BREAKING CHANGE: . В нем должно содержаться то, что изменилось в API. Например, BREAKING CHANGE: environment variables now take precedence over config files.
  10. Типы отличные от feat и fix могут (MAY) быть использованы в ваших commit’ах.
  11. Единицы информации, которые составляют обычные commit’ы, не должны (MUST NOT) трактоваться разработчиками как регистрозависимые, за исключением BREAKING CHANGE, который всегда должен быть написан прописными буквами.
  12. Знак ! может (MAY) быть добавлен перед : в тип/контекст, чтоб обратить внимание на изменения. Строка BREAKING CHANGE: description должна (MUST) быть добавлена в тело (body) или подвал (footer), если используется ! в префиксе.

Почему нужно использовать Conventional Commits

FAQ

Как я должен писать сообщения commit’ов на начальной стадии разработки?

Мы рекомендуем писать сообщения commit’ов так, как будто вы уже выпустили продукт. Как правило, кто-то, например, ваши коллеги, уже используют ваш код. И они хотят знать, что исправилось, что изменилось, какие нарушения обратной совместимости появились и т.д.

В каком регистре я должен писать заголовки commit’ов?

Любой регистр можно использовать, но лучше во всей истории использовать один стиль.

Что мне делать, если commit должен содержать больше одного типа?

Вернитесь назад и сделайте несколько commit’ов, если это возможно. Часть из преимуществ использования Conventional Commits - это его способность побуждать делать более организованные коммиты и PR’ы.

Разве это не препятствует быстрому развитию и быстрой интеграции?

Это препятствует быстрому развитию в неорганизованном виде. Это помогает быстро двигаться в проектах с несколькими участниками.

Могут ли Conventional Commits заставить разработчиков ограничивать их типы commit’ов, потому что им придется думать об этих типах?

Conventional Commits побуждают делать больше commit’ов с определенными типами, такими как fix. Кроме того, гибкость Conventional Commits позволяет вашей команде создавать свои собственные типы и изменять их с течением времени.

Как это связано с правилами семантического управления версиями SemVer?

fix тип commit’а должен быть отражен в PATCH-релизе. feat тип commit’а должен быть отражен в MINOR-релизе. Commit’ы с BREAKING CHANGE в теле или подвале, независимо от типа, должны быть отражены в MAJOR-релизе.

Как я должен версионировать мои расширения к спецификации Conventional Commits, например, @jameswomack/conventional-commit-spec?

Мы рекомендуем использовать SemVer для релизов ваших расширений к этой спецификации (и рекомендуем делать эти расширения!).

Что мне делать, если я случайно использовал не тот тип commit’а?

Что если вы использовали тип, который имеет спецификацию, но это неправильный тип. Например, fix вместо feat

Перед слиянием или релизом ошибки, мы рекомендуем использовать git rebase -i для редактирования истории commit’ов. После release, исправления будут отличаться в зависимости от того, какие инструменты вы используете.

Когда вы использовали тип, не описанный спецификацией, например, feet вместо feat

Это не конец света, это просто обозначает, что коммит будет упущен при работе утилит, основанных на спецификации.

Должны ли все мои соавторы использовать спецификацию Conventional Commit?

Нет! Если ваш рабочий процесс основан на использовании слияния (squash) Git, сопровождающий проекта может очистить историю всех предыдущих commit’ов при их слиянии, не добавляя рабочей нагрузки на случайные commit’ы. Обычно, рабочий процесс строится на том, что ваша система Git автоматически объединяет (squash) все предыдущие commit’ы перед pull-запросом и предоставляет форму сопровождающему проекта для ввода нового commit’а.