この記事は、2020年3月にITnewsで公開した「コミットメッセージについてのガイド」の記事転載です。
以前「バージョン1」と呼ばれるディスク上にアーカイブファイルがあった時代もありました。ほとんどの方がGitHub、Gitlab、Bitbucketなどのバージョン管理ツールを使用しているはずなので、コードをプロジェクトに追加するたびにコミットを作成する必要があるはずです。あなたのコミットメッセージが優れているどうか疑問に思ったことはありますか? おそらくコミットメッセージを書くのが好きな人はあまりいないと思います。コードをプッシュしようとするたびに、なぜコミットメッセージを書かなければならないのか疑問に思うことでしょう。結局のところ、その変更が満足のいくものではないのはありませんか?
この記事では、良いコミットそのものについてではなく、良いコミットメッセージの書き方について説明します。この二つの議題は似てるところもあるかもしれませんが…。(バージョン管理に関するベストプラクティスをまとめたTobiasGünther氏の良い記事がこちらに載っています)。
##なぜコミットメッセージが大切なのか?
変更は十分ですか? 明らかに、答えはノーですよね。でも、その理由はなんでしょうか?
コミットメッセージには多くの用途があります。これはプロジェクトで仲間の開発者とコミュニケーションを取る第一の手段です。変更は、あなたが何かを達成する方法を設定するものですが、コミットメッセージはあなたがそれをする理由を説明するものです。開発者によって、なぜそのようなコードが書かれているのかその理由が明確に分かるように、しっかりとしたコンテキストが必要です。きちんとした説明があれば、開発者がなぜこのコードをプッシュしたのかという理由を尋ねるために、貴重な時間を使う必要がなくなるのです。オープンソースプロジェクトのような場合、忙しいメンテナーは、きちんと書かれたコミットメッセージのような最小限の情報がなければ、あなたのコードを読むことさえしません。
Peter Hutterer氏がこの素晴らしい記事「コミットメッセージについて」で述べているように、コミットメッセージは同じ会社の仲間のためだけでなく将来の自分ためでもあります。
どのソフトウェアプロジェクトも共同プロジェクトなのです。少なくとも2人の開発者がプロジェクトに関わっています。元の開発者と、数週間または数か月後の元の開発者です。一連の思考、考えのつながりが元居た場所を離れたときに、そうなります。
Peter Hutterer-コミットメッセージについて
プロジェクトは、長期的に維持されるように設計されています。コードの一部を書いた数年後に、なぜそのように書いたのかを自問することがあります。今週、たった6か月前にコーディングした関数でもそういうことが起こりました。よく書かれたコミットメッセージがあれば、この変更を書いたときの心の状態に簡単に戻れます。
コミットメッセージに意識を向けるようになると、日常生活もシンプルになります。 いくつかのgit コマンドの log、rebase、cherry-pick…などの意味のあるコミット履歴で、いくつかのツールがより興味深いものになります。旅行から戻ってきたとき、単純なgit log –prettyがあると、あなたが休暇で仕事を休んでいた間に仕事仲間がどんな作業をしたのか多くの情報を教えてくれるでしょう。 良いコミットメッセージを書くことで、変更を分割しなければならず、git log -pでより簡単に確認できるようになります。
レビューに関して、開発者が行った何らかの変更に基づいてコードのリベースに苦労したことはありますか? コミットメッセージに本当の意味が含まれていると、変更が行われた理由を把握しやすくなります。そして、そうすることで rebase の結果がより予測できるようになります。 別の例としては、git blameコマンドというものがあります。これは、特定のコード行数のコンテキストを与えてくれるものです。これはコードの一部をリファクタリングする場合に非常に便利です。
最後に大事なこと言いますね。よく構造化されたコミット履歴のおかげで、プロジェクトの2つのバージョン間で変更ログを生成し、ユーザーに変更内容を通知できるようになります。
これは、良いコミットメッセージを書くのに時間をかける大きな理由です。
##良いコミットメッセージの書き方
今までお話してきたことから、コミットメッセージがいかに重要であるか、ご理解いただいたと思います。そこで、次に良いコミットメッセージの書き方についてお話ししましょう。 私が取り組んでいるimmutadotというプロジェクトからコミットメッセージをいくつか選びました。 ご覧のとおり、これらのコミットメッセージには一貫性がないため、読みにくくなっています。
fix #72 unnecessary object copies
Fixing unshift documentation examples
seq.chain path parameter fix #18
Remove built files
Add tests
Add Circle CI base config
Rename es -> src
Add lang package with toggle, fix exports
Core package
これらのコミットメッセージでは、スタイル、コンテンツ、メタデータの点でいくつかの間違いがあります。 Chris Beams氏は、「Gitコミットメッセージの作成方法」という記事の中で次の3つのポイントを正確に説明しています。
スタイル…マークアップシンタックス、ラップマージン、文法、大文字にすべきところを大文字にすること、句読点が大事。当てずっぽうではなく、これらをきちんと書いて、すべてをできるだけシンプルにします。最終的には、非常に一貫性のあるログになり、読むだけでなく、実際に定期的に読み取られやすくなります。
コンテンツ… コミットメッセージの本文(もし、ある場合)にはどのような情報が含まれているべきですか? 含まれてはいけない情報が入っていませんか?
メタデータ… 発行追跡ID、プルリクエスト番号などをどのように発行すべきなのでしょうか?参照すべき?
Chris Beams-Gitコミットメッセージの書き方
大文字で書かれたメッセージ、2つのコミットのみのメタデータがあることがわかります。最終的に、一部のメッセージの内容は非常に軽く、コミットが何をするのかわかりません。 同じ記事で、Chrisは良いコミットメッセージを書く7つのルールについても書いています。
- 件名と本文を空白行で区切る
- 件名を50文字以内にする
- 件名を大文字にする
- 件名をピリオドで終了しない
- 件名に命令文を使用する
- 本文を72文字で折り返す
- 本文で「何を、なぜ、どのように」を説明する
Chris Beams-Gitコミットメッセージの書き方
私は個人的にこれらのルールのサブセットを適用します:
- 件名を50文字に制限する
- 件名を大文字にする
- 件名に命令文を使用する
文字数の制限によりシンプルになるだけでなく(これは素晴らしいテクニックです)、Tim Popeの記事「Gitコミットメッセージに関する注意事項」で説明されているように、多くのツールに適しています。
私は、「余りに完璧なものを求めすぎて、本来の目的を見失う(「完璧は十分の敵だ」)」傾向にあると思います。だからこそ、コミットメッセージ本文について話すのを省略したのです。サマリー行に関しては色々とお話しておくべきこともあると思います。 ただし、対応するルールを1つ追加します:
- プルリクエスト/マージリクエスト トラッキングIDを追加する
ほとんどの場合、コードレビュープロセス中にGitHub、Gitlabなどのツールを使用して議論します。変更に関するすべての情報は、少なくともそこで説明されます。 IDの追跡に関するこのルールを追加して、関連するプル/マージリクエストを見つけやすくしました。 リポジトリマネージャーソリューションを変更すると、この貴重なコンテキスト情報がすべて失われ、トラッキングIDが意味のないものになってしまうため、コミットの本文を書く方がトラッキングIDを追加するよりも優れています。
以下は、私が取り組んでいるgitmoji-changelogと呼ばれる、それらのルールに従うプロジェクトの最近の例です。
Make core independent from the git client (#171)
Upgrade Docker image version (#167)
Add maven preset (#172)
Add a generic preset using configuration file (#160)
Improve error messages for preset system (#161)
Publish Canary version on master push (#141)
一貫したスタイルを持つことで、断然読みやすくなります。 変更のコンテキストを把握でき、メタデータに直接アクセスできるようになります。とにかく重要なことは、チーム内で一般的なルールを見つけて、適切に構造化されたコミット履歴を保持することです。これらを見つけるのに役立ついくつかのルールがありますが、これについては後で説明します。
何のメッセージを書くべきかわからない場合は、コミットを小さな部分に分割すればよいでしょう。Peter Hutterer氏の記事「コミットメッセージについて」には、コミットパッチが論理的でないために適切なコミットメッセージを見つけることが難しくなっている例がいくつか記載されています。
###おまけ
ペアプログラミングやモブプログラミングの方法でプログラミングをする場合は、コミットメッセージに同僚の名前を忘れずに追加してください。
$ git commit -m "Refactor usability tests.
>
>
Co-authored-by: name <name@example.com>
Co-authored-by: another-name <another-name@example.com>"
##コミットルール
先ほど説明したように、チームのコミットルールを設定する必要があります。インスピレーション与えてくれる源になる可能性のあるオープンソースのコミットルールが存在します。 また、コミットメッセージの作成、変更ログの生成、リリースの作成…などに役立つツールを含むエコシステム全体が付属しています。コミットメッセージの作成、変更ログの生成、リリースの作成などには多くの時間がかかることがあります。 十分に文書化されているため、独自のコミットメッセージルールに関するドキュメントを書く必要はありません。
それでは次にConventional Commitsとgitmojiの2つについて説明します。
###Conventional Commits
これは、Angularコミットメッセージガイドラインから着想を得た仕様です。 以下のような興味深いルールがいくつかあります。
- コミットの前にタイプ(feat、fix)を付ける必要がある
- コードベースの特定のセクション(monorepoにとっては本当に興味深い)を指し示すためにスコープが設置される場合がある
- 重大な変更はフッターセクションに含める必要がある
この仕様を使用してコミットメッセージを構成する方法を次に示します。
<type>[optional scope]:description>
[optional body]
[optional footer(s)]
詳細については、仕様の説明をご一読ください。
###gitmoji
私はgitmojiコミットルールが好きです。 絵文字を使用してコミットを分類するところが気に入っています。私は視覚で認識するのが得意な人間なので、そんな私にはぴったりですが、こういった性質がすべての人に備わっているわけではないことは理解しています。
gitmoji-changelogからの以前のコミットの例では、ごまかしがありました。あなたが今推測したように、不足している部分があります。
:recycle: Make core independent from the git client (#171)
:whale: Upgrade Docker image version (#167)
:sparkles: Add maven preset (#172)
:sparkles: Add a generic preset using configuration file (#160)
:recycle: Improve error messages for preset system (#161)
:construction_worker: Publish Canary version on master push (#141)
これらのテキストエイリアスは、Slack、Discordなどのツールで広く使用されています。GitHubやGitLabなどのリポジトリマネージャーツールのほとんどは、これらを解釈してUIで適切に表示します。
♻️ Make core independent from the git client (#171)
🐳 Upgrade Docker image version (#167)
✨ Add maven preset (#172)
✨ Add a generic preset using configuration file (#160)
♻️ Improve error messages for preset system (#161)
👷♂️ Publish Canary version on master push (#141)
私はどのような変更がコミットを行うかが一目で分かるので、このルールが好きです。 コミットメッセージの作成に役立つgitmoji-cliと呼ばれるcliがくっついていています。私は、そのための変更ログジェネレーターを作成しました。
このようなものがもっとたくさんあります。これらはガイドラインであるということを覚えておいてください。それらを組み合わせて、ニーズを満たすものが得られます。例えば、monorepoで作業する場合、従来のコミットのスコープの概念でgitmojiルールを使う、などです。