Gitのコミットメッセージの書き方(2023年ver.)
本記事のモチベーション
約8年前、Gitを使い始めたときに以下の記事を公開したところ、想像以上の反応をいただきました。
当時はSubversionからGitに移行し、試行錯誤をしている中だったこともあり、多くの反応をいただけたことはモチベーションのひとつでした。
ただ、時が経ち、当然かもしれませんが現在は当時と違う書き方をしており、思想として変わっていない部分はあるものの、今でもときどきLikeをいただく中で、アップデートを全くしないのは誠実じゃないなと感じていました。
というわけで、現在のフォーマットも数年後には変わっている可能性が高いですが、その時々のスナップショットを公開することにも何らか意味があるかなと思い、「今の僕はこうコミットメッセージを書いているよ」というのをまとめました。
Gitを使う環境
開発フローやホスティングサービスごとのUIのdiffによって、最適なフォーマットは変わると思うので、僕の環境を記しておきます。
- 開発フロー
- 基本的にはチケット(Issue)およびPull(Merge) Request駆動開発を採用しています
- ホスティングサービス
- ほとんどGitHubですがGitLabもたまに使用しています
コンセプト
以下の3つのコンセプトで運用しています。
- 巨人の肩の上に立つ
- フォーマットを覚えるコストが低い
- ミニマルな手がかりが掴める
フォーマットを設ける理由
様々な理由があると思いますが、僕は以下のように考えています。
- そもそも、コミットメッセージは…
- リポジトリという地層の断片
- 自分を含む未来の開発者に向けて書くもの
- リポジトリの歴史やコンテキストを理解するための手がかりであるべき
- という前提のもと、一定の規律=フォーマット(Not ルール)を設けることで…
- チームがスケールしてもその手がかりを失わないようにしたい
- フォーマットを設けることで考えることを一つでも減らしたい
フォーマット
Semantic Commit Messageを採用しています。
- フォーマット:
<Type>: <Emoji> #<Issue Number> <Title>
- 例:
feat: ✨ #123 ログイン機能の実装をする
- TypeとTitleは必須
- Issue Numberは強く推奨
- Emojiは任意
- Description(スリーライン)は任意
Type
- どんなコミットなのかシュッと分かるようにPrefixとしてコミットの種別を書きます
- Semantic Commit Messageと同様の種別を使います
-
chore
- タスクファイルなどプロダクションに影響のない修正
-
docs
- ドキュメントの更新
-
feat
- ユーザー向けの機能の追加や変更
-
fix
- ユーザー向けの不具合の修正
-
refactor
- リファクタリングを目的とした修正
-
style
- フォーマットなどのスタイルに関する修正
-
test
- テストコードの追加や修正
-
過去、オレオレルールで運用していたこともありましたが、種別が覚えられなかったり、浸透しなかったりしたので、強い気持ちでSemantic Commit Messageのレールの上に乗っています。
Emoji
- Typeをより"カラフル"にするためにEmojiを書きます
- 何でも構いませんがgitmojiから選ぶのが便利だと思います
- ただし、Emojiを覚えるコストがあるので必須ではありません
- 僕はほとんどのプロジェクトで書いていません
Issue Number
- そのコミットに紐づくIssue番号を書きます
- リンクになって、トラッキングがしやすいため
- Issueを作っていないケースやhotfixの場合は省略可とします
- ただし、Issueがあると修正意図が理解しやすいのでIssueを作成することを強く推奨します
- なお、デフォルトの設定だと
#
がコメント扱いになるのでこの位置に置いています
Subject
- いわゆる、変更内容を書きます
- 現在形で(「◯◯した」ではなく「◯◯する」)書くこととします
- 文字数は特に制限しませんが、20〜30文字以内が適切だと思います
- Descriptionは必須ではありません
- 僕はほぼ書いていません
良いコミットメッセージとは?
よくコミットメッセージにはWhyを書くべしという言説がありますが、最近はそこまでこだわらないようになりました。もちろん、その主張には賛同していて、Whyを書ければベストですが、ワンライナーでWhyまで書くのは難易度が高く、そこまでコミットメッセージが"カラフル"にならないと思っています。
そうなると、Whyを書くためにdescriptionを活用する必要がありますが、descriptionにWhyを書くのであれば、コミットメッセージにIssueを紐付けて、Issue(もしくはPull Request)側でWhyを丁寧に書いたほうが辿りやすいと個人的には思っています。また、コミットメッセージ単体でWhyを伝えるよりもその束であるIssueやPull RequestでWhyを伝えたほうが意図が分かりやすいことが多いと感じています。
ですので、僕はコミットメッセージにはほぼ必ずIssueを紐付け、WhyはIssueやPull Requestで担保し、Subjectはある程度Whatに寄った書き方をしています。もちろん、「〜のために◯◯した」といったような表現が出来る場合はそう書いていますし、「テストを書く」や「Lintエラーを修正する」と言ったような"カーディナリティ"が高いコミットメッセージは避けるべきだと考えています。
日本語か?英語か?
統一されていることが大切なので、チームでコンセンサスが取れていれば、どちらでも(もちろん、日本語や英語以外でも)良いと思いますが、僕の場合、ドメスティックなチーム、ドメスティックなサービスであれば日本語で書くことが多いです。
過去、張り切って英語で書いていたこともあったのですが、ネイティブじゃないのでどうしても時間がかかったり、急いでいると雑に「Fix a sorting bug」 的な文法も怪しいカーディナリティの高いコミットメッセージを書いたりしてしまうことがあり、本末転倒だなと思って英語で書くことは少なくなりました。
もちろん、グローバルなチームでは英語で書いたほうがいいケースがほとんどだと思いますし、英語が書けて損はないので、英語を採用すること自体は全く問題ないですが、ネイティブじゃない場合は、自分だけではなく、チーム全員でそれなりの覚悟が必要かなと思います。
その他
- Merge CommitやRevert Commitはこのフォーマットに従う必要はありません
- コミットの粒度は小さくすることを基本的な考え方とします
- ただし、常に1行の修正ごとにコミットすればOKというわけでは必ずしもなく、レビュアーがPull Requestのコミット一覧を見たときに"ストーリー"が分かることを意識する
自分だけのコミットメッセージでライバルに差をつけろ!
冒頭でも少し触れましたが、ここに書いてあることがただの一つの正解ではないですし、僕自身は現時点でこれがベストかなと思っていますが、明日にでもよりよい書き方を発見し、この書き方をすぐ捨てる可能性もあります。ですので、この記事もいずれ古くなってしまうとは思うのですが、コミットメッセージに限らず、日々試行錯誤し続けることがソフトウェアエンジニアリングの面白さのひとつだと思っているので、この記事が誰かのコミットメッセージを考えるきっかけになれば幸いです。
Discussion
これは面白そうで、あなたが証明しようとしているビジョン、すべてに幸運がありますように!幸運がありますように!
I like it :)