NHN Cloud NHN Cloud Meetup!

Gitのコミットメッセージをうまく作成する7つのルール

この記事は、Chris BeamsのHow to Write a Git Commit Messageブログの内容を簡単にまとめた資料で、翻訳・編集して、役に立つ内容を追加したものです。

Gitのコミットメッセージをうまく作成すべき理由

なぜコミットメッセージをうまく書く必要があるのか?理由は色々ありますが、うまく書かれたコミットメッセージが有益であるという事実は、多くのプログラマが同意することでしょう。そのうち代表的な3つの例を挙げてみます。

  1. コミットログの読みやすさ
  2. より良いコラボレーションとレビュープロセス
  3. コード保守の容易さ

「良いコミットメッセージについて考えることは素晴らしいアイデアだと思う。しかし、良いメッセージの正解があるかは分からない。個人によって良いコミットメッセージと捉える基準が異なるためだ。多くの人々が共感できる良いコミットメッセージをうまく作るためのルールはないだろうか?」

今回の記事では、良いコミットメッセージの普遍的な基準について紹介します。

良いGitのコミットメッセージを作成する7つのルール

以下は、コミットメッセージをEnglishで作成する場合に最適化されているルールです。

  1. タイトルと本文の間は1行空ける
  2. タイトルは英字基準で50文字以内
  3. タイトルの最初の文字を大文字にする
  4. タイトルの末尾は.禁止
  5. タイトルは命令文にする
  6. 本文は英字基準で72文字ごとに改行する
  7. 本文はどのようによりも何をなぜに合わせて作成する

1.タイトルと本文の間は1行空ける

タイトルと本文の間に空白行を追加するのは、想像以上に効果的なテクニックです。まずgit commitmanページを参照すると、次のような文章が表示されます。

Though not required, it’s a good idea to begin the commit message with a single short (less than 50 character) line summarizing the change, followed by a blank line and then a more thorough description. The text up to the first blank line in a commit message is treated as the commit title, and that title is used throughout Git. For example, git-format-patch(1) turns a commit into email, and it uses the title on the Subject line and the rest of the commit in the body.

要約すると、コミットメッセージは50文字以内のタイトル(概要)空白行本文(説明文)で構成すると良い、というものです。
これは強制事項ではないので、すべてのコミットメッセージをタイトルと本文で構成する必要はありません。場合によっては、次の例のように変更内容を1行に要約したコミットメッセージが効果的なこともあります。

直前のコミットで、`README.md`にある太字を1字更新
二重引用符漏れ..--; 修正
昨日付で保存場所のURLを変更、URLのみをアップデート

しかし、通常であれば、整ったコミットメッセージを作成したい場合はGitのルールに従うのが良いでしょう。
次はタイトル、空白行、本文で構成されている例です。

Derezz the master control program

MCP turned out to be evil and had become intent on world domination.
This commit throws Tron's disc into MCP (causing its deresolution)
and turns it back into a chess game.

git logでは、このコミットメッセージが次のように表示されます。

$ git log
commit 42e769bdf4894310333942ffc5a15151222a87be
Author: Kevin Flynn <kevin@flynnsarcade.com>
Date:   Fri Jan 01 00:00:00 1982 -0200

 Derezz the master control program

 MCP turned out to be evil and had become intent on world domination.
 This commit throws Tron's disc into MCP (causing its deresolution)
 and turns it back into a chess game.

大きな違いはありません。ここでgit log –onelineオプションを使ってみます。

$ git log --oneline
42e769 Derezz the master control program

すると、タイトルのみ表示されます。空白行で区切らない場合は、次のように表示されます。

$ git log --oneline
42e769 Derezz the master control program MCP turned out to be evil and had become intent on world domination. This commit throws Tron's disc into MCP (causing its deresolution) and turns it back into a chess game.

git shortlogというコマンドがあり、このコマンドを使ってログを見ると、タイトルと本文が空白行で分けられ、コミットは次のように表示されます。

$ git shortlog
Kevin Flynn (1):
    Derezz the master control program

Alan Bradley (1):
    Introduce security program "Tron"

Ed Dillinger (3):
    Rename chess program to "MCP"
    Modify chess program
    Upgrade chess program

Walter Gibbs (1):
    Introduce protoype chess program

2.タイトルは英字基準で50文字以内

「50文字以内」はそれほど難しい制約事項ではありません。この制約があることで、簡潔に要約されたタイトルになることでしょう。
50文字が難しい場合は、まず「69文字」に挑戦してみましょう。

3.タイトルの最初の文字を大文字にする

これはほぼ英文法の問題です。

✕ accelerate to 88 miles per hour

〇 Accelerate to 88 miles per hour

4.タイトルの末尾は.禁止

これも英文法の問題です。タイトルには、通常ピリオドをつけません。

✕ Open the pod bay doors.

〇 Open the pod bay doors

5.タイトルは命令文にする

おそらくこの記事で一番馴染みがなく、あまり知られていない最も重要な内容ではないでしょうか。タイトルを作成したり、1行メッセージでコミットする場合、コミットメッセージの最初の文章は命令文にしましょう。これは最初の単語を動詞にするという意味です。例えば、このようなメッセージを考えてみましょう。

認証メソッドを直す

* CABVerification.java: 15番目の認証メソッドの引数を現在のポリシーに合うように修正した
* JSONFormat.java: このコミットはこのファイルに適切なロギングメソッドを追加する
* MainView.java: 若干のリファクタリング

このメッセージのタイトルを次のように直します。

認証メソッドの修正

なぜ英文のコミットメッセージのタイトルを命令文にする必要があるのでしょう。

上述のように普段、命令は読者に失礼な感じがあり、ログメッセージという状況にそぐわない感じがします。外国人も私たちと同じような感覚を持っているでしょう。ところが、命令文はGitのコミットのタイトルとしては非常に相応しいのです。その理由の1つは、Git自身が自動コミットを作成するときに命令を使用しているからです。例えば、git mergeを実行したとき、コミットメッセージのデフォルトは次のように表示されます。

Merge branch 'myfeature'

git revert コマンドを実行すると、次のように表示されます。

Revert "Add the thing with the stuff"

This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

Githubでフルリクエストの「Merge」ボタンをクリックすると、次のように表示されます。

Merge pull request #123 from someuser/somebranch

このようにコミットメッセージを命令文で作成することは、Gitのビルトインコンベンション(Built-in Convention)にそのまま従うことを意味します。このためコミットタイトルを命令文で作成すると、自動メッセージで満たされたコミット間に自然に溶け込むことでしょう。前の項目で述べたgit shortlogのような他のコマンドとも連携できます。

もちろん、これはタイトルや1行コミットメッセージの話であり、コミットメッセージの本文を命令文で始める必要はありません。自然な形で、過去形や現在進行形などを使って変更点を記述するのが良いと思います。

簡単なヒントを紹介します。タイトルを作成するときにどのような文法で記述すべきかよく分からない場合、次の文章の後にタイトルを配置して、文法が合うか確認してみましょう。

  • If applied, this commit will {タイトル}

例文を表示します。

  • (If applied, this commit will)Refactor subsystem X for readability
  • (If applied, this commit will)Update getting started documentation
  • (If applied, this commit will)Remove deprecated methods
  • (If applied, this commit will)Release version 1.0.0
  • (If applied, this commit will)Merge pull request#123 from user/branch

シンプルな例文はこちら。

  • (If applied, this commit will)Fixed bug with Y
  • (If applied, this commit will)Changing behavior of X
  • (If applied, this commit will)More fixes for broken stuff
  • (If applied, this commit will)Sweet new API methods

このルールは、「タイトル」にのみ適用されます。「本文」を作成する場合は平叙文で作成するのが良いでしょう。

6.本文は英字基準で72文字ごとに改行する

Gitは自動でコミットメッセージの改行をしません。(git logにスタイルを指定して、自動改行が適用されたログ出力を作成することはあります)単純なgit logコマンドを入力するだけで見栄えの良いメッセージを作成したい場合は、適切な位置でエンターキーを押して行を変える必要があり、その適切な位置として、72文字をお薦めします。

git logにスタイルを指定する方法が分からない場合は、Gitがインストールされたシステムのコマンドラインに次のコマンドを入力して使用してみてください。カスタムスタイルのオプションが適用されたgit logを実行する”alias”を作成する設定です。一度設定した後、ログの確認は、git logの代わりにgit lgと省略して入力できます。自動改行の適用はもちろんのこと、きれいになったGitのログを見てみましょう。実際に使用しているコマンドで、既存のgit logも元の通りに動作します。この設定を~/.gitconfigファイルに作成しておけば、毎回入力する必要がなく、次回のGit実行から常に適用されます。

$ git config --global alias.lg "log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold red)%h%C(reset) : %C(bold green)(%ar)%C(reset) - %C(cyan)<%an>%C(reset)%C(bold yellow)%d%C(reset)%n%n%w(90,1,2)%C(white)%B%C(reset)%n'"

[図1] Git lg実行結果

[図2] Git lg –oneline実行結果

7.本文はどのようにより何をなぜに合わせて作成する

良い例としてBitcoin Coreプロジェクトに実際に使用されたコミットメッセージを紹介します。

commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <pieter.wuille@gmail.com>
Date:   Fri Aug 1 22:57:55 2014 +0200

   Simplify serialize.h's exception handling

   Remove the 'state' and 'exceptmask' from serialize.h's stream
   implementations, as well as related methods.

   As exceptmask always included 'failbit', and setstate was always
   called with bits = failbit, all it did was immediately raise an
   exception. Get rid of those variables, and replace the setstate
   with direct exception throwing (which also removes some dead
   code).

   As a result, good() is never reached after a failure (there are
   only 2 calls, one of which is in tests), and can just be replaced
   by !eof().

   fail(), clear(n) and exceptions() are just never called. Delete
   them.

おまけ – コミットメッセージでGithub issueを自動終了させる

もしコミットメッセージを英文で作成したいなら、良いヒントを1つ紹介します。Githubにはコミットメッセージに特定の単語を使って、自動でissueを終了させる便利な機能が搭載されています。この予約語はコミットメッセージの中のどこからでも使用可能です。

キーワード #issue番号

Githubがissue終了と認識するキーワードは、次のとおりです。

  • close
  • closes
  • closed
  • fix
  • fixes
  • fixed
  • resolve
  • resolves
  • resolved

各キーワードにおいて機能の違いは全くなく、文法や文脈に合わせて使用できます。ただし、close系列は全般的な開発issue、fix系列はバグフィックスやホットフィックスissue、resolve系列は問い合わせや要望に対応したissueに使用するのが適当だという慣例があります。では例文を紹介します。

# タイトルから1つのissueにクローズを適用した事例
Close #31 - refactoring wrap-up

* This is wrap-up of refactoring main code.
* main.c
  * removed old comments
  * fixed rest indentations
  * method extraction at line no. 35


# 本文からissueの処理を行った事例
Update policy 16/04/02

* This closes #128 - cab policy, closes #129 - new hostname, and fixes #78 - bug on logging.
* cablist.txt: changed ACL due to policy update delivered via email on 16/04/02, @mr.parkyou
* hostname.properties: cab hostname is updated
* BeautifulDeveloper.java: logging problem on line no. 78 is fixed. The `if` statement is never happening. This deletes the `if` block.

このようにコミットを作成してプッシュすると、プッシュしたブランチに基づいてissueが自動で終了します。例えば、Githubリポジトリのdefault branchをmasterに設定しておくと、masteブランチにコミットしてからプッシュすれば、すぐにその番号のissueが終了します。developブランチにプッシュしてもissueは終了いませんが、後でdevelop -> master Mergeなったときに終了します。

References

NHN Cloud Meetup 編集部

NHN Cloudの技術ナレッジやお得なイベント情報を発信していきます
pagetop