Git入門:バージョン管理のきほん

良いコミットメッセージの書き方

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

このレッスンで分かること

  • 1 行目 50 字以内・命令形といった、コミットメッセージの具体的な型
  • 「何をしたか」ではなく「なぜそうしたか」を本文に書く理由
  • Conventional Commits の書式と、それが必須ではない理由

メッセージは半年後の自分に宛てた説明書

コミットメッセージは、誰も読まないメモではありません。バグの原因を探すときに最初に読まれる資料です。

たとえば本番でバグが出て、原因の行を特定したとします。次にやるのは、その行をいつ誰がなぜ変えたのかを調べることです。

ターミナル

$ git log --oneline src/price.js 7e5c3d9 修正 4d9b7e1 対応 8f3c1a2 fix

これでは何も分かりません。3 つのコミットを全部開いて差分を読むしかなく、しかも読んでも「なぜ」は分かりません。

対して、こう書かれていれば話が早く済みます。

ターミナル

$ git log --oneline src/price.js 7e5c3d9 消費税の端数処理を切り捨てから四捨五入に変更 4d9b7e1 送料無料の判定を税抜金額で行うよう修正 8f3c1a2 商品価格の計算ロジックを追加

差分を開く前に、探している変更がどれか見当が付きます。この差はメッセージの書き方だけで生まれます。

メッセージが効いてくる場面は、ほかにもあります。

  • git log --oneline で履歴をざっと追うとき
  • git log --grep="送料" のように、キーワードでコミットを探すとき
  • プルリクエストの一覧で、レビュー担当が中身を推し量るとき
  • 障害の報告書に「いつ何を変えたか」を書くとき

どれも「差分を開かずに判断したい」場面です。メッセージは、差分を読む手間を省くために書きます。

「書く時間がもったいない」と感じるかもしれませんが、逆です。書くのに 30 秒、読み解くのに 10 分。あとから読む人が 5 人いれば、差は 50 分になります。しかも、その 5 人のうち何回かは自分自身です。

1 行目の型を決める

コミットメッセージは 1 行目(件名)と本文に分かれます。まず 1 行目のルールを 4 つだけ覚えてください。

ルール理由
50 字以内に収めるgit log --oneline や GitHub の一覧で切れずに読める幅
何をしたかを 1 文で言い切る一覧で流し読みされる前提。修飾は要らない
末尾に句点を付けない見出しであって文章ではない。幅の無駄にもなる
1 行目と本文の間に空行を空けるGit は空行までを件名として扱う

最後のルールは書式の決まりです。空行を入れないと、Git は本文まで件名の一部と見なし、git log --oneline の表示が壊れます。

ターミナル

$ git commit -m "消費税の端数処理を四捨五入に変更" -m "国税庁の資料に合わせて切り捨てから変更した。旧仕様の請求書との差額は最大 1 円。"

-m を 2 回書くと、Git が間に空行を入れてくれます。エディタで書く場合は自分で空行を空けてください。

50 字という上限には根拠があります。git log --oneline は 1 行にハッシュ値と件名を並べるので、長い件名は折り返すか切れます。GitHub のコミット一覧も、およそ 70 文字を超えると省略記号で切られます。切られた先に大事な情報を置くと、誰にも読まれません。

日本語なら、50 字はかなり書けます。「消費税の端数処理を切り捨てから四捨五入に変更」で 24 字です。収まらないなら、たいていはコミットの範囲が大きすぎます。

件名が「〜と〜を修正」という形になったら要注意です。1 つのコミットに 2 つの話が入っている合図で、あとから片方だけ取り消したくなったときに困ります。1 コミット 1 目的が原則です。

命令形で書く

英語で書く場合、1 行目は命令形にそろえるのが慣習です。Added でも Adds でもなく Add です。

プレーンテキスト

Add validation to the login form Fix crash when the cart is empty Remove unused helper functions

理由は 2 つあります。ひとつは、Git 自身が自動生成するメッセージ(Merge branch ...Revert ...)が命令形なので、そろえると読み口が統一されること。もうひとつは「このコミットを適用すると何が起きるか」という視点で書けることです。

英語のコミットでよく使う動詞は、実際にはそれほど多くありません。

動詞使う場面
Add機能・ファイル・テストを足した
Fix不具合を直した
Remove不要なコードや設定を消した
Update既存のものを新しくした
Refactor動きを変えずに構造を整えた
Rename名前を変えた

日本語で書くなら、命令形そのものは不自然になります。「〜する」の形か体言止めにそろえてください。どちらでもよいので、チームの中で混ぜないことが大事です。

プレーンテキスト

ログインフォームにバリデーションを追加する カートが空のときのクラッシュを修正する

プレーンテキスト

ログインフォームへのバリデーション追加 カートが空のときのクラッシュ修正

良い例と悪い例を見比べる

抽象的なルールより、対比の方が早く身に付きます。

悪い例何が問題か良い例
修正何をどう直したのか一切分からないカートが空のときに落ちる不具合を修正する
いろいろ変更1 コミットに複数の話が混ざっている合図変更ごとにコミットを分ける
バグ修正 #123issue を開かないと内容が分からない送料計算で離島の追加料金が抜ける不具合を修正する
src/price.js を変更差分を見れば分かることを繰り返している消費税の端数処理を四捨五入に変更する
レビュー指摘対応何を指摘され何を直したのかが残らない価格計算の重複コードを共通関数にまとめる
wip履歴に残す価値がないコミットを整理してから push する

いちばん多い間違いは、いちばん下から 3 行目です。ファイル名や関数名を書いても、それは差分を見れば分かります。メッセージに書くべきは、差分からは読み取れない情報です。

書けたかどうかを判定する簡単な方法があります。書いた件名を読んで、何のファイルを触ったコミットか見当が付き、かつファイル名そのものは書かれていないなら合格です。

プレーンテキスト

悪い → src/cart.js の checkTotal を修正 良い → カートの合計金額に送料が二重加算される不具合を修正する

下の文はファイル名を書いていませんが、カート周りの話だと分かります。しかも「何がどう間違っていたか」まで伝わります。

git commit -m "修正" を打ちそうになったら、それは 1 コミットの範囲が大きすぎる合図であることが多いです。1 文で説明できないほど混ざっているから「修正」としか書けないのです。まず変更を分けて、stash やステージの部分追加で小さくコミットしてください。

本文には「なぜ」を書く

件名で「何をしたか」は伝わります。本文に書くべきは、差分を読んでも絶対に分からない「なぜ」です。

プレーンテキスト

消費税の端数処理を四捨五入に変更する 請求書の合計金額が会計システムの計算と 1 円ずれる問い合わせが 3 件あった。 原因は端数を切り捨てていたことで、取引先の会計システムは四捨五入していた。 切り捨てのまま会計システム側に合わせる案も検討したが、 先方のシステムは変更できないため、こちらを合わせる方針とした。 2026-08-01 以前に発行済みの請求書には影響しない。

ここに書かれている情報は、どれも差分からは読み取れません。問い合わせが何件あったか、採用しなかった案は何か、既存データへの影響はあるか。半年後に「なぜここを四捨五入にしたのか」と疑問を持った人は、この本文で納得できます。

本文に書くと価値があるのは、次のようなものです。

  • そう直すに至った背景(不具合の再現条件、要望の出どころ)
  • 検討したが採用しなかった案と、その理由
  • 影響範囲や、あえて直さなかった部分
  • 参照すべき issue やドキュメントへのリンク

逆に、変更したファイル名の羅列や、差分を日本語に訳しただけの説明は要りません。

書き方の目安として、次の 3 つの箱を埋めるつもりで書くと形になります。

  1. 何が問題だったか 「請求書の合計が会計システムと 1 円ずれる」
  2. なぜそうなっていたか 「端数を切り捨てていた」
  3. どう判断したか 「先方は変更できないのでこちらを合わせる」

本文の 1 行の長さは 72 文字くらいで折り返すのが慣習です。ターミナルの git log は本文をそのまま表示するため、極端に長い行は読みにくくなります。日本語なら 35 字前後で改行する感覚です。

なお、GitHub を使うチームでは、本文に Closes #123 と書くとプルリクエストのマージ時に issue が自動で閉じます。これは Git ではなく GitHub の機能です。詳しくはプルリクエストを出すで扱います。

本文は必須ではありません。件名だけで理由まで伝わる小さな変更に、無理やり本文を付ける必要はありません。判断の基準は「半年後の自分が件名だけ読んで納得できるか」です。納得できないなら本文を書いてください。

Conventional Commits という書式

チームによっては、件名の先頭に決まった種類の名前を付ける Conventional Commits という書式を使います。

プレーンテキスト

feat: ログインフォームにバリデーションを追加する fix: カートが空のときのクラッシュを修正する docs: READMEにセットアップ手順を追記する refactor: 価格計算の重複コードを共通関数にまとめる test: 送料計算のテストケースを追加する chore: 依存ライブラリを更新する

feat は新機能、fix は不具合修正、といった具合に、コミットの種類を機械が読める形にします。影響範囲をかっこで補うこともあります。

プレーンテキスト

fix(cart): カートが空のときのクラッシュを修正する

利点は、履歴を機械的に集計できることです。リリースノートを自動生成したり、feat が入ったらマイナーバージョンを上げる、といった自動化がやりやすくなります。

ただし、これは必須のルールではありません。 Git の機能でもなければ、業界の標準でもなく、ひとつの慣習です。自動生成の仕組みを使っていないチームで導入すると、意味の薄い prefix を付ける作業が増えるだけになりがちです。chorerefactor のどちらか迷う時間も生まれます。

判断の基準は単純です。リリースノートやバージョンの自動生成を使うなら採用する。使わないなら、日本語で分かりやすく書く方が価値があります。参加するリポジトリの git log を先に読んで、そこの流儀に合わせてください。

書式そのものより大事なのは、チームの中でそろっていることです。feat を使う人と使わない人が混在した履歴は、どちらの流儀よりも読みにくくなります。個人で始めたリポジトリなら、自分で 1 つ決めて最後まで通してください。

よくある失敗と、そこからの戻し方

書き終えてから「主語が抜けていた」「typo があった」と気づくのはよくあることです。

ターミナル

$ git log --oneline -1 7e5c3d9 消費税の端数処理を四捨五入に変更すす

まだ push していなければ、直前のコミットは作り直せます。

ターミナル

$ git commit --amend -m "消費税の端数処理を四捨五入に変更する" [main 2b8f6a1] 消費税の端数処理を四捨五入に変更する 1 file changed, 4 insertions(+), 2 deletions(-)

ただし、push 済みのコミットに対してこれをやると履歴が食い違って事故になります。その線引きは直前のコミットを直す(commit --amend)で扱った通りです。push 済みのメッセージは、原則として直しません。少し恥ずかしくても、そのまま残す方が安全です。

事前に防ぐなら、git commit-m なしで実行してエディタで書くようにしてください。1 行だけ打ち込むより、書いた文を読み返しやすくなります。テンプレートを用意しておく手もあります。

ターミナル

$ git config --global commit.template ~/.gitmessage

~/.gitmessage に件名と本文の枠を書いておけば、毎回それが開きます。Windows の Git Bash でも同じパス指定で動きます。PowerShell を使う場合は、~ がユーザーフォルダに解決されないことがあるので C:/Users/<ユーザー名>/.gitmessage のように書いてください。

テンプレートの中身は、この程度で十分です。

プレーンテキスト

# 件名(50字以内・句点なし) # なぜこう直したか # 検討したが採用しなかった案 # 影響範囲

# で始まる行はコミット時に取り除かれるので、書きかけの見出しをそのまま残しても履歴には入りません。埋めなかった行は消して保存してください。

この章のポイント
  • 1 行目は 50 字以内、句点なし、1 文で言い切る。本文との間に空行を入れる
  • 英語なら命令形、日本語なら「〜する」か体言止めでそろえる。混ぜない
  • 差分から読み取れる「何を」ではなく、読み取れない「なぜ」を本文に書く
  • Conventional Commits は自動生成を使うチームには有効。必須のルールではない