
Gitコミットメッセージ規約
読みやすい履歴のつくり方とルール化
Gitのコミットメッセージを読みやすくする書き方を解説。件名と本文の基本構造、Conventional Commitsのtype一覧、テンプレート設定や自動チェックまでコマンド付きで紹介します。
シリーズ:Git 実践シリーズ
01
ソース管理ワークフロー
02
タグの使い方(ローカル / Gitea Web)
03
コミットメッセージ規約
04
rebase の使い方
05
GitHub / Gitea Actions
コミットメッセージは「未来の自分とチームへのメモ」です。コードを書いた本人ですら、半年後には「この変更、何のためだっけ?」と忘れます。git log を開いたときに 「いつ・何を・なぜ変えたか」が一目で追える履歴 かどうかは、メッセージの書き方ひとつで大きく変わります。
この記事では、読みやすいコミットメッセージの 基本構造 から、広く使われている Conventional Commits という規約、そして チームでルールを揺らさず守る仕組み までを順番に解説します。難しい話ではなく、今日から1コミット目で実践できる内容です。
💡 前提条件
git add →git commit →git push の流れが一通りできれば大丈夫です。第1回・第2回を読んでいなくても、この記事単体で完結します。
なぜコミットメッセージにこだわるのか
コミットメッセージが整っていると、次のような場面で効いてきます。
たとえば障害が起きて「いつから挙動が変わったのか」をgit log やgit bisect で追うとき、各コミットが何をしたか明確なら原因の特定が一気に速くなります。プルリクエストのレビューでも、まとまったメッセージは「この変更の意図」をレビュアーへ正確に伝えます。さらに、規約に沿ったメッセージは CHANGELOG(変更履歴)の自動生成 やバージョン番号の自動決定にもつながります。
悪い例と良い例
まずは「あるある」な悪い例と、改善後を見比べてみましょう。
✗ 伝わらないコミット
fix
更新
いろいろ修正
wip
あ
何を直したのか・なぜ変えたのかが分からない。後から履歴を見ても価値がなく、レビューや障害調査で役に立たない。
✓ 伝わるコミット
fix: ログイン失敗時に500が返る不具合を修正
feat: 記事一覧にページネーションを追加
docs: READMEにセットアップ手順を追記
種類(fix / feat / docs)と要約がひと目で分かる。履歴を上から眺めるだけで「何が起きてきたか」を追える。
コミットメッセージの基本構造
規約に入る前に、どんなスタイルでも共通する「土台」を押さえます。コミットメッセージは 件名(subject)・本文(body)・フッター(footer) の3部構成で考えます。
feat(auth): ログイン機能を追加 ← 件名:50文字以内・要約
← 空行(必須)
パスワード認証とセッション管理を実装した。 ← 本文:なぜ/何を(任意)
ログイン状態は7日間保持する仕様とする。
Refs #123 ← フッター:関連Issueなど(任意)件名だけは必須で、本文とフッターは必要なときだけ書きます。小さな変更なら件名1行で十分です。件名を書くときのポイントは次の通りです。
| ルール | 理由 |
|---|---|
| 件名は50文字程度まで | git log --oneline やツール表示で折り返さず読める |
| 件名の末尾に句点(。)を付けない | 見出しであり文章ではないため。表示が締まる |
| 件名と本文の間に空行を1行入れる | Gitが件名と本文を正しく区別できる |
| 本文は「なぜ」を中心に書く | 「何を」変えたかはdiffを見れば分かる。意図はメッセージにしか残らない |
| 1コミット=1つの意味のある変更 | 後で取り消す・追う単位が明確になる |
✨ 「何を」より「なぜ」
diff を見れば「コードがどう変わったか」は分かります。メッセージにしか残せないのは 「なぜその変更が必要だったか」 です。本文を書くときは、変更内容の繰り返しではなく背景や判断理由を書くと、未来の自分が救われます。
Conventional Commits ― 広く使われる規約
「件名の頭に種類を付ける」というスタイルを標準化したのが Conventional Commits です。形式はとてもシンプルです。
type(scope): 要約
# 例
feat(blog): 記事の予約投稿に対応
fix(api): 空のタイトルで投稿できる不具合を修正
docs: インストール手順を更新 # scopeは省略可type は変更の「種類」、scope は「どこを変えたか」(任意)、その後ろに要約を書きます。type によく使われる値は次の通りです。
| type | 意味 | 例 |
|---|---|---|
feat | 新機能の追加 | 記事の検索機能を追加 |
fix | バグ修正 | 404ページのリンク切れを修正 |
docs | ドキュメントのみの変更 | READMEを更新 |
style | 動作に影響しない整形(空白・セミコロン等) | インデントを統一 |
refactor | 挙動を変えないコード改善 | 関数を分割して整理 |
perf | パフォーマンス改善 | 一覧取得のクエリを最適化 |
test | テストの追加・修正 | ログインのテストを追加 |
build | ビルドや依存関係の変更 | Viteをv6に更新 |
ci | CI設定の変更 | Actionsのワークフローを追加 |
chore | その他の雑務(上記に当てはまらない) | .gitignoreを整理 |
✨ まずは feat / fix / docs / chore から
最初から全部覚える必要はありません。 新機能=feat、バグ修正=fix、ドキュメント=docs、それ以外の雑務=chore の4つで始めれば、履歴は十分読みやすくなります。慣れてきたら refactor や test を足していきましょう。
破壊的変更(Breaking Change)の示し方
互換性が壊れる変更(既存の使い方が動かなくなる変更)は、特別に目立たせます。type の後ろに! を付けるか、フッターにBREAKING CHANGE: を書きます。
feat(api)!: 投稿APIのレスポンス形式を変更
BREAKING CHANGE: postsキーをdataキーに変更した。
旧クライアントは data 配下を参照するよう修正が必要。 日本語で書くか、英語で書くか
これは正解が一つではありません。チームの方針に合わせるのが大前提ですが、判断材料として次のように整理できます。
| 方針 | メリット | 向いているチーム |
|---|---|---|
type は英語+要約は日本語 | 規約の互換性を保ちつつ、内容が母語で速く読める | 日本語話者中心のチーム(おすすめ) |
| すべて英語 | OSSや海外メンバーとの共有がスムーズ | 国際的なプロジェクト |
| すべて日本語 | 書く心理的ハードルが最も低い | 個人開発・社内限定 |
✨ 迷ったら「type英語+要約日本語」
本記事の例で使っているfeat: 記事一覧にページネーションを追加 のスタイルです。Conventional Commits のツール群(後述のcommitlint等)はtype 部分さえ規約どおりなら動くため、要約を日本語にしても自動化の恩恵を受けられます。
実際にコミットしてみる
1行で書く場合
$ git add .
$ git commit -m "feat: 記事一覧にページネーションを追加" 本文も書く場合
-m を2回以上指定すると、それぞれが段落として扱われ、件名と本文の間に空行が入ります。
$ git commit -m "fix: ログイン失敗時に500が返る不具合を修正" \
-m "未定義のセッションを参照していたのが原因。null判定を追加した。" 長い本文を書くなら、-m を付けずに実行してエディタで編集するのが快適です。
# エディタが開く(既定はvi。設定で変更可)
$ git commit
# コミットメッセージ用エディタをVS Codeにする例
$ git config --global core.editor "code --wait" コミットテンプレートで型を用意する
便利設定
毎回フォーマットを思い出すのは大変です。 テンプレート を用意しておくと、git commit 時に雛形が自動で表示されます。
# <type>(<scope>): <要約 50文字以内>
#
# 本文(なぜこの変更が必要か。72文字くらいで折り返す)
#
# type: feat / fix / docs / style / refactor / perf / test / build / ci / chore
# フッター例: Refs #123 , BREAKING CHANGE: ...# このテンプレートを全リポジトリの既定にする
$ git config --global commit.template ~/.gitmessage✨ # で始まる行は無視される
テンプレートの# から始まる行はコメント扱いで、実際のコミットメッセージには含まれません。ガイドとして残しておけるので、書き方を忘れても安心です。
チームでルールを揺らさず守る
「規約を決めても、気づくと守られていない」——これはよくある悩みです。人の注意力に頼らず、 仕組みで弾く のが解決策です。代表的な2段構えを紹介します。
① コミット時に自動チェック(commitlint + husky)
手元でコミットした瞬間に、規約に沿っているか検査して、ダメなら止める方法です。Node.js環境のプロジェクトで広く使われます。
# 検査ツールとGitフック管理ツールを導入
$ npm install --save-dev @commitlint/cli @commitlint/config-conventional husky
# commitlintの設定(Conventional Commits準拠ルールを使う)
$ echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
# huskyを初期化し、commit-msgフックで検査を実行
$ npx husky init
$ echo 'npx --no-install commitlint --edit "$1"' > .husky/commit-msgこれで規約に反するメッセージはコミット自体が拒否されます。
$ git commit -m "いろいろ修正"
#✖ subject may not be empty / type may not be empty
#✖ found 2 problems
#husky - commit-msg hook exited with code 1 (error)⚠️ ️ バージョンで手順が変わります
husky は v9 でフックの書き方が変わるなど、メジャーバージョンによって導入手順が異なります。上記は代表的な流れなので、実際は各ツールの最新ドキュメントを確認してください。.husky/ 配下のフックは コミットして共有 することでチーム全員に適用されます。
② サーバー側でも検査(次回への布石)
手元のフックは各自が無効化できてしまうため、最終的には サーバー側(CI)でも検査 するのが堅実です。Gitea には GitHub Actions 互換の Gitea Actions があり、push や Pull Request のたびにコミットメッセージを検査するワークフローを組めます。これは本シリーズの「Actions編」で詳しく扱います。
🎯 ルール化の考え方
「テンプレートで書きやすくする」→「手元のフックで弾く」→「サーバーのCIで最終チェック」の3段構え。最初からすべてやる必要はなく、まずはテンプレートとtypeの統一だけでも履歴は劇的に読みやすくなります。
コマンドリファレンス
| コマンド | コマンド内容 |
|---|---|
git commit -m "feat: ..." | 件名だけのコミット。type付きで書く。 |
git commit -m "件名" -m "本文" | 件名と本文を分けて書く(間に空行が入る)。 |
git commit | エディタを開いて長いメッセージをじっくり書く。 |
git commit --amend | 直前のコミットメッセージを書き直す(push前限定が安全)。 |
git config --global commit.template ~/.gitmessage | コミットテンプレートを登録する。 |
git log --oneline | 件名だけを一覧表示。規約の効果を確認できる。 |
トラブルシュート
❓ 直前のコミットメッセージを間違えた
まだ push していなければgit commit --amend で書き直せます。すでに push 済みの共有ブランチでは、履歴の書き換えが他人に影響するため原則避けてください(rebaseの回で詳しく扱います)。
❓ どの type を使えばいいか毎回迷う
挙動が変わればfeat かfix 、変わらなければrefactor /style /docs /chore 、と二段階で考えると決めやすいです。それでも迷うものはchore に寄せて構いません。
❓ 1つのコミットに複数の変更が混ざってしまう
「件名に『〜と〜』が入る」ときは分割のサインです。git add -p で変更を部分的にステージングすると、意味のある単位でコミットを分けられます。
❓ huskyのフックがチームメンバーで動かない
フックは.husky/ をコミットして共有し、各自がnpm install を実行している必要があります。クローン直後にセットアップが走っていないと有効になりません。READMEに導入手順を書いておくと確実です。
まとめ
今回学んだこと
- コミットメッセージは「なぜ変えたか」を未来に残すための記録
- 基本構造は「件名(50字・句点なし)+空行+本文+フッター」
- Conventional Commits は
type(scope): 要約の形。まずは feat / fix / docs / chore から - 破壊的変更は
!かBREAKING CHANGE:で目立たせる - 日本語チームは「type英語+要約日本語」が書きやすく自動化とも両立
- テンプレート(
commit.template)で書きやすくする - commitlint+huskyで自動チェック。最終的にはCI(Gitea Actions)でも検査
🎯 この記事のゴール
type を付けて要約を書く——たったこれだけで、git log --oneline がプロジェクトの「変更ストーリー」として読めるようになります。まずは次のコミットからfeat: やfix: を付けて、履歴の見やすさの違いを体感してみてください。
