目次
- コミットの基本原則
- 良いコミットメッセージの書き方
- コミット単位の決め方
- コミットの標準フォーマット
- 基本的なコミットコマンド
- コミットの修正と管理
- ブランチ戦略とコミット
- コミットフック
- CI/CDとの連携
- トラブルシューティング
1. コミットの基本原則
1.1 原子的コミット
- 1つの論理的変更 = 1つのコミット:1つの機能追加や1つのバグ修正を1つのコミットにまとめる
- 複数の変更を混ぜない:異なる目的の変更は別々のコミットに分ける
- なぜ重要か:レビュー、バグ追跡、リバート(変更取り消し)が容易になる
1.2 コミットのタイミング
- 頻繁にコミットする:作業を小さな単位に分けて頻繁にコミットする
- 動作する状態でコミットする:コードが正常に動作する状態でコミットすべき
- 一日の終わりにはコミットする:未コミットの変更を残して帰らない
1.3 理想的なコミットサイズ
- 小さすぎない:「変数名の変更」だけなど、微小すぎる変更は避ける
- 大きすぎない:300〜500行程度の変更を目安とする
- 例外:リファクタリングや依存関係の更新など、大規模な変更が必要な場合もある
2. 良いコミットメッセージの書き方
2.1 基本構造
[タイプ] 簡潔な要約(50文字以内)
詳細な説明(72文字で改行)。何を変更したかではなく、
なぜ変更したのかに焦点を当てる。
関連する課題番号やリンク:
Fixes #123
Related to #456
2.2 要約行のポイント
- 命令形で書く:「追加した」ではなく「追加する」
- 大文字で始める
- 末尾にピリオドを付けない
- 50文字以内に収める
- **何を」ではなく「なぜ」と「どのように」を説明する
2.3 詳細説明のポイント
- 空行で要約と区切る
- 72文字で折り返す
- 変更の背景や理由を説明する
- 関連するバグチケットやドキュメントへの参照を含める
2.4 良いコミットメッセージの例
[feat] ユーザー認証にGoogle OAuthを追加
セキュリティ強化のため、既存のパスワード認証に加えて
Google OAuthによるログインオプションを追加。
- ユーザーはGoogleアカウントでログイン可能
- 初回ログイン時に自動的にユーザーアカウントを作成
- 既存ユーザーは設定画面でGoogleアカウントと紐付け可能
Refs #142
2.5 レビュー指摘対応のコミットメッセージ例
[review] ユーザー登録フォームのバリデーション強化
PR #67のレビュー指摘対応:
- メールアドレスの正規表現バリデーションを修正
- パスワード強度チェックを追加
- エラーメッセージの表示方法を改善
Addresses review comments in PR #67
3. コミット単位の決め方
3.1 機能単位でコミットする
- 1つの機能 = 1つ以上の論理的なコミット
- 機能完成前の中間コミット:WIP (Work In Progress) プレフィックスを付ける
- 例:ログイン機能の追加なら「ログインフォームのUI作成」「認証ロジックの実装」「エラーハンドリングの追加」など
3.2 ファイル種別ごとに分ける場合
- フロントエンドとバックエンドの変更を分ける
- データベースマイグレーションは別コミット
- 設定ファイルの変更は分離する
3.3 リファクタリングのコミット
- 機能変更とリファクタリングを混ぜない
- リファクタリングは必ず別コミットにする
- テスト追加も別コミットが望ましい
3.4 指摘対応のコミット
- レビュー指摘は対応ごとに分ける:1つの指摘に対して1つのコミット
- 指摘内容をコミットメッセージに含める:どの指摘に対応したのかを明確にする
-
プレフィックスを付ける:
[fix]
や[review]
などでレビュー指摘対応と分かるようにする -
関連チケット番号を参照する:
Fixes #123
やAddresses review comment in PR #45
- 複数の小さな指摘はまとめる場合も:関連性の高い軽微な修正は1つのコミットにまとめる
- 大きな修正は分割する:設計変更を伴う指摘は複数コミットに分ける
4. コミットの標準フォーマット
4.1 Conventional Commits
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
4.1.1 よく使われるタイプ
- feat: 新機能
- fix: バグ修正
- docs: ドキュメントのみの変更
- style: コードの動作に影響しない変更(フォーマット等)
- refactor: バグ修正や機能追加ではないコード変更
- perf: パフォーマンス改善
- test: テストの追加・修正
- chore: ビルドプロセスやツールの変更、ライブラリの更新など
- ci: CI設定ファイルやスクリプトの変更
4.1.2 スコープの例
- auth: 認証関連
- api: API関連
- ui: ユーザーインターフェース
- db: データベース
- config: 設定
4.2 Gitmojiの活用
コミットメッセージの先頭に絵文字を付けて視覚的に分かりやすくする手法:
- ✨ (feat): 新機能
- 🐛 (fix): バグ修正
- 📚 (docs): ドキュメント
- 🎨 (style): スタイル・フォーマット
- ♻️ (refactor): リファクタリング
- ⚡️ (perf): パフォーマンス改善
- ✅ (test): テスト
- 🔧 (chore): 設定変更
4.3 日本語環境でのコミットメッセージ
- 英語と日本語の混在を避ける:どちらかに統一
- 日本語の場合:文字化けに注意(UTF-8を使用)
- チーム内で統一する:フォーマットをチーム内で統一して一貫性を保つ
5. 基本的なコミットコマンド
5.1 新規コミット作成
# 変更をステージングエリアに追加
git add <ファイル名>
# 全ての変更をステージングエリアに追加
git add .
# 変更をコミット
git commit -m "コミットメッセージ"
# 変更を追加してコミット(新規ファイルは追加されない)
git commit -am "コミットメッセージ"
5.2 変更の確認
# 変更状態の確認
git status
# 変更内容の詳細表示
git diff
# ステージングされた変更の詳細表示
git diff --staged
# コミット履歴の表示
git log
# コミット履歴をグラフ表示
git log --graph --oneline --decorate
5.3 部分的なコミット
# ファイルの一部だけをステージング
git add -p <ファイル名>
# 対話的にステージングする変更を選択
git add -i
6. コミットの修正と管理
6.1 直前のコミットの修正
# 直前のコミットメッセージを変更
git commit --amend -m "新しいメッセージ"
# 変更を追加して直前のコミットを修正(メッセージ変更なし)
git add <ファイル名>
git commit --amend --no-edit
# 変更を追加して直前のコミットを修正(メッセージも変更)
git add <ファイル名>
git commit --amend
6.2 コミットの打ち消し
# コミットを打ち消す新しいコミットを作成
git revert <コミットハッシュ>
# 直前のコミットを打ち消す
git revert HEAD
6.3 複数コミットの統合(squash)
# 直近のn個のコミットを対話的に操作
git rebase -i HEAD~n
# masterからの全コミットを対話的に操作
git rebase -i master
リベース中の操作:
- pick: コミットをそのまま使用
- reword: コミットを使用するがメッセージを変更
- edit: コミットを使用するが修正のために停止
- squash: 直前のコミットと統合し、コミットメッセージも統合
- fixup: 直前のコミットと統合するがメッセージは破棄
- drop: コミットを削除
6.4 コミットの分割
# 対象のコミットまでリベース
git rebase -i <分割したいコミットの1つ前のハッシュ>
# 対象コミットを「edit」に変更して保存
# コミットを取り消す(変更はステージングに残る)
git reset HEAD^
# 変更を部分的にステージングして複数のコミットに分ける
git add <ファイル1>
git commit -m "1つ目のコミット"
git add <ファイル2>
git commit -m "2つ目のコミット"
# リベースを続行
git rebase --continue
6.5 コミットの移動(cherry-pick)
# 特定のコミットを現在のブランチに適用
git cherry-pick <コミットハッシュ>
# 複数のコミットを順番に適用
git cherry-pick <コミットハッシュ1> <コミットハッシュ2>
# コミットをマージせずに変更だけをステージングエリアに追加
git cherry-pick -n <コミットハッシュ>
6.6 レビュー指摘後の修正戦略
# 1. 既存コミットを修正する方法
git add <修正ファイル>
git commit --amend --no-edit # 直前のコミットに修正を追加
# 2. 新しいコミットを作成する方法
git add <修正ファイル>
git commit -m "[review] レビュー指摘対応: フォームバリデーション修正"
# 3. fixupコミットを作成する方法(後でsquashする前提)
git add <修正ファイル>
git commit --fixup=<修正対象のコミットハッシュ>
# 4. PRマージ前にfixupコミットを自動的に統合
git rebase -i --autosquash <ブランチのベースコミット>
7. ブランチ戦略とコミット
7.1 Feature Branch Workflow
- 特徴:機能ごとに専用ブランチを作成
- コミット方針:機能ブランチでは小さな作業単位で頻繁にコミット
- マージ前:関連コミットをsquashして整理してからマージするケースが多い
- PRサイズ:レビューしやすいサイズ(通常500行以下)に保つ
7.2 Git Flow
- 特徴:develop, feature, release, hotfix, masterの5種類のブランチを使用
-
コミット方針:
- feature:自由にコミット
- develop:機能完成時にマージ
- release:バグ修正のみコミット
- hotfix:緊急バグ修正
- master:製品リリース時のみ
7.3 Trunk Based Development
- 特徴:主にmainブランチに直接コミット、短命なフィーチャーブランチを使用
-
コミット方針:
- 小さな変更を頻繁にmainに統合
- フィーチャートグル(機能フラグ)を活用して未完成機能を本番環境に含める
- CI/CDパイプラインとの統合が重要
7.4 レビュープロセスとコミット戦略
- プルリクエスト前のコミット整理:レビュー前にsquashや分割で整理
-
レビュー中のコミット:
- 追加コミット方式:指摘対応を新しいコミットとして追加(履歴が追える)
- 修正コミット方式:元のコミットを修正(歴史を綺麗に保つ)
-
Fixupコミット方式:
--fixup
フラグでマーク付けして後で統合
-
レビュー後のコミット整理:マージ前に
git rebase -i
で整理する -
コミット署名:
git commit -s
でSigned-off-byを追加(一部のプロジェクトで必須)
8. コミットフック
8.1 pre-commitフック
#!/bin/bash
# .git/hooks/pre-commit
# 実行権限を付与: chmod +x .git/hooks/pre-commit
# コードスタイルチェック
npm run lint
# テスト実行
npm test
# 0以外の終了コードならコミットを中止
if [ $? -ne 0 ]; then
echo "テストに失敗しました。コミットを中止します。"
exit 1
fi
8.2 commit-msgフック
#!/bin/bash
# .git/hooks/commit-msg
# 実行権限を付与: chmod +x .git/hooks/commit-msg
# コミットメッセージが規約に沿っているか確認
commit_msg=$(cat $1)
pattern="^(feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert)(\(.+\))?: .{1,50}$"
if ! [[ $commit_msg =~ $pattern ]]; then
echo "コミットメッセージが規約に沿っていません。例: feat: 新機能の追加"
exit 1
fi
8.3 Husky(Node.jsプロジェクト用)
package.jsonの設定例:
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.js": ["eslint --fix", "prettier --write", "git add"],
"*.{json,md}": ["prettier --write", "git add"]
},
"commitlint": {
"extends": ["@commitlint/config-conventional"]
}
}
9. CI/CDとの連携
9.1 コミットトリガーのCI/CD
- Pull Requestごとにテスト実行
- 特定ブランチへのコミットで自動デプロイ
- コミットメッセージに基づく処理分岐
9.2 GitHub Actionsの例
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
9.3 SemVerとの連携
- feat: コミットで minor バージョンアップ
- fix: コミットで patch バージョンアップ
- BREAKING CHANGE: を含むコミットで major バージョンアップ
10. トラブルシューティング
10.1 間違ったコミットをした場合
# 直前のコミットを取り消し(変更は保持)
git reset --soft HEAD^
# 直前のコミットを完全に取り消し(変更も破棄)
git reset --hard HEAD^
# 特定のコミットまで戻る(変更は保持)
git reset --soft <コミットハッシュ>
# 特定のコミットまで完全に戻る(変更も破棄)
git reset --hard <コミットハッシュ>
10.2 プッシュ済みのコミットを修正する場合
# 履歴を書き換えた後に強制プッシュ(注意:チーム開発では要相談)
git push --force-with-lease
10.3 コミット履歴が複雑になった場合
# 履歴を単純化して表示
git log --oneline --graph --decorate
# コミットをグループ化して表示
git shortlog -sn
# 特定ファイルのコミット履歴を表示
git log --follow -- <ファイル名>
10.4 コンフリクトの解決
# コンフリクトの確認
git status
# マージツールを使用してコンフリクトを解決
git mergetool
# コンフリクト解決後のコミット
git commit
10.5 一時的に変更を退避
# 作業中の変更を一時保存
git stash
# 保存した変更を確認
git stash list
# 保存した変更を復元(スタックから削除)
git stash pop
# 保存した変更を復元(スタックに保持)
git stash apply
11. 補足:GitとCIツールの統合事例
11.1 GitHub
- Semantic Release: コミットメッセージからバージョンを自動決定
- Danger: PRの自動レビュー
- CodeClimate: コード品質の自動チェック
11.2 GitLab
- GitLab CI: パイプラインの自動実行
- GitLab Pages: ドキュメントの自動生成
- Auto DevOps: コミットからデプロイまでの自動化
11.3 Bitbucket
- Bitbucket Pipelines: コミットごとのCI/CD
- Code Insights: コード品質レポート
- Jira連携: コミットメッセージからJiraチケット更新
このチートシートが実務のGit運用の参考になれば幸いです。チームでの開発では、コミットルールを明文化し共有することで、より効率的な開発とコードレビューが可能になります。