📖

Conventional Commits - コミットメッセージ仕様

2022/10/17に公開

こんな形式のコミットメッセージ見たことないでしょうか。

chore(deps): update all non-major dependencies

これはConventional Commitsに従ったものです。

結論

多くのOSSや開発現場は、(明確に宣言していないものの)Conventional Commitsに影響を受け、PRタイトルやコミットメッセージを設定しています。

シンプルな仕様ですので、チームで開発する上で知っておくと良いと思います。

仕様/用途編

本家仕様

Conventional Commitsは、Gitのコミットメッセージの形式に関する仕様。
シンプルでドキュメントも分かりやすく、こちらのサマリから大体つかめる。

コミットメッセージに含める情報

  1. commit type:コミットの種別を表現する
    • fix:バグ修正
    • feat:機能追加
    • 上記以外の種別もチームで決めて使ってOK(※標準的な仕様は後述)
  2. optional scope:commit typeに付け加えて、コミットが対象とするコードベース内の領域を補足する。省略可
  3. description:概要。一般的にコミットメッセージの1行目に記載する内容
  4. optional body:本文。一般的にコミットメッセージの1行目の後、空白行を空けて、3行目以降の記載する内容。(一般的慣習に従い)省略可
  5. optional footer(s):フッタ。一般的にコミットメッセージの本文の後、空白行を空けて、最後に記載する内容。(一般的慣習に従い)複数指定可、省略可
    • BREAKING CHANGE: <description>:破壊的変更を表すフッタ。commit type(scopeがある場合はscope)の後ろに!をつけることでも表現可。両方の指定も可。

コミットメッセージの構成方法

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

シミュレーション

コミットメッセージに含める情報が、

  • commit typefix
  • scopeapi
  • descriptionprevent racing of requests
  • optional bodyIntroduce a request id, and add request id to any log message.
  • footer(s)
    • BREAKING CHANGE: drop support for Node 6
    • Refs: #123(※一般的なフッタ)

だとすると、以下のようになる。

fix(api)!: prevent racing of requests

Introduce a request id, and add request id to any log message.

BREAKING CHANGE: drop support for Node 6
Refs: #123

周辺仕様

commit typeは、前述のとおり、fixfeat以外も使うことができる。
一般には、commitlintというツールの定義が普及している。

[
  'build',
  'chore',
  'ci',
  'docs',
  'feat',
  'fix',
  'perf',
  'refactor',
  'revert',
  'style',
  'test'
]

https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum

用途

特徴として、commit typeやfooterのBREAKING CHANGEが、SemVerと対応している。

  • BREAKING CHANGE:MAJOR
  • feat:MINOR
  • fix:PATCH

そのため、

  1. 人にとって理解しやすい
    • コミットの意図や対象とする機能について、コンテキストをひと目で共有できる
  2. 自動化しやすい

採用状況編

多くのOSSや開発現場は、明確に宣言していないものの、Conventional Commitsに影響を受け、PRタイトルやコミットメッセージを設定しています。

実際にJS界隈のOSSリポジトリを無作為に10個ほど調べたところ、7個がConventional Commits形式に従っていました。

以下に3つの例をまとめます。

例1. Nuxt

Nuxtは、コントリビュータに対して、PRタイトルをConventional Commits形式で書くように明確に求めている。

https://v3.nuxtjs.org/community/contribution/#final-checklist

実際にこのルールは守られている模様。

https://github.com/nuxt/framework/pulls

一方で、上記ガイドラインにコミットメッセージについての言及はない。

実際にリポジトリをみてみると、PRはSquash & Mergeされている。Squash & Merge時、PRタイトルがコミットメッセージになるため、PRタイトルに関するルールだけで、ツリーがConventional Commitsに保たれているようである。

例2. Fastify

Fastifyは、明確にはConventional Commits採用を宣言していない模様。
https://github.com/fastify/fastify/blob/main/docs/Guides/Contributing.md#how-to-contribute

しかし、実際は大半のコントリビュータがConventional Commitsに倣っている。
https://github.com/fastify/fastify/pulls?q=is%3Apr+is%3Aclosed

例3. React

Reactは、明確にはConventional Commits採用を宣言しておらず、Conventional Commitsに意図的に従っていない模様。
コントリビュータが作成するPRタイトルに一貫性がないように見える。

https://ja.reactjs.org/docs/how-to-contribute.html

https://github.com/facebook/react/pulls?q=is%3Apr+fix%3A+is%3Aclosed

追伸1

先日、NuxtにPRを送るにあたって、NuxtのContribution guidelineを読んで、初めてConventional Commitsを知りました。
https://v3.nuxtjs.org/community/contribution/

副業先現場でも確認したところ、「無意識に従っていた」とのことでしたので、やはり多くのエンジニア・現場がどこかでConventional Commitsに触れて、影響を受けているようです。

仕様自体はシンプルだったのですが、採用状況や広まり方が興味深かったので、まとめることにしました。

追伸2

この記事はMagicodeから移転しました。
2022年7月あたりの記事となります。

Discussion