Files
gh-wasabeef-claude-code-coo…/commands/semantic-commit.md
2025-11-30 09:05:37 +08:00

1138 lines
32 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Semantic Commit
大きな変更を意味のある最小単位に分割して、セマンティックなコミットメッセージと共に順次コミットします。外部ツールに依存せず、git 標準コマンドのみを使用します。
### 使い方
```bash
/semantic-commit [オプション]
```
### オプション
- `--dry-run` : 実際のコミットは行わず、提案されるコミット分割のみを表示
- `--lang <言語>` : コミットメッセージの言語を強制指定 (en, ja)
- `--max-commits <数>` : 最大コミット数を指定 (デフォルト: 10)
### 基本例
```bash
# 現在の変更を分析して、論理的な単位でコミット
/semantic-commit
# 分割案のみを確認 (実際のコミットなし)
/semantic-commit --dry-run
# 英語でコミットメッセージを生成
/semantic-commit --lang en
# 日本語でコミットメッセージを生成
/semantic-commit --lang ja
# 最大 5 個のコミットに分割
/semantic-commit --max-commits 5
```
### 動作フロー
1. **変更分析**: `git diff HEAD` で全変更を取得
2. **ファイル分類**: 変更されたファイルを論理的にグループ化
3. **コミット提案**: 各グループに対してセマンティックなコミットメッセージを生成
4. **順次実行**: ユーザー確認後、各グループを順次コミット
### 変更分割の核心機能
#### 「大きな変更」の検出
以下の条件で大きな変更として検出:
1. **変更ファイル数**: 5 ファイル以上の変更
2. **変更行数**: 100 行以上の変更
3. **複数機能**: 2 つ以上の機能領域にまたがる変更
4. **混在パターン**: feat + fix + docs が混在
```bash
# 変更規模の分析
CHANGED_FILES=$(git diff HEAD --name-only | wc -l)
CHANGED_LINES=$(git diff HEAD --stat | tail -1 | grep -o '[0-9]\+ insertions\|[0-9]\+ deletions' | awk '{sum+=$1} END {print sum}')
if [ $CHANGED_FILES -ge 5 ] || [ $CHANGED_LINES -ge 100 ]; then
echo "大きな変更を検出: 分割を推奨"
fi
```
#### 「意味のある最小単位」への分割戦略
##### 1. 機能境界による分割
```bash
# ディレクトリ構造から機能単位を特定
git diff HEAD --name-only | cut -d'/' -f1-2 | sort | uniq
# → src/auth, src/api, components/ui など
```
##### 2. 変更種別による分離
```bash
# 新規ファイル vs 既存ファイル修正
git diff HEAD --name-status | grep '^A' # 新規ファイル
git diff HEAD --name-status | grep '^M' # 修正ファイル
git diff HEAD --name-status | grep '^D' # 削除ファイル
```
##### 3. 依存関係の分析
```bash
# インポート関係の変更を検出
git diff HEAD | grep -E '^[+-].*import|^[+-].*require' | \
cut -d' ' -f2- | sort | uniq
```
#### ファイル単位の詳細分析
```bash
# 変更されたファイル一覧を取得
git diff HEAD --name-only
# 各ファイルの変更内容を個別に分析
git diff HEAD -- <file>
# ファイルの変更タイプを判定
git diff HEAD --name-status | while read status file; do
case $status in
A) echo "$file: 新規作成" ;;
M) echo "$file: 修正" ;;
D) echo "$file: 削除" ;;
R*) echo "$file: リネーム" ;;
esac
done
```
#### 論理的グループ化の基準
1. **機能単位**: 同一機能に関連するファイル
- `src/auth/` 配下のファイル → 認証機能
- `components/` 配下のファイル → UI コンポーネント
2. **変更種別**: 同じ種類の変更
- テストファイルのみ → `test:`
- ドキュメントのみ → `docs:`
- 設定ファイルのみ → `chore:`
3. **依存関係**: 相互に関連するファイル
- モデル + マイグレーション
- コンポーネント + スタイル
4. **変更規模**: 適切なコミットサイズの維持
- 1 コミットあたり 10 ファイル以下
- 関連性の高いファイルをグループ化
### 出力例
```bash
$ /semantic-commit
変更分析中...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
検出された変更:
• src/auth/login.ts (修正)
• src/auth/register.ts (新規)
• src/auth/types.ts (修正)
• tests/auth.test.ts (新規)
• docs/authentication.md (新規)
提案されるコミット分割:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
コミット 1/3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
メッセージ: feat: implement user registration and login system
含まれるファイル:
• src/auth/login.ts
• src/auth/register.ts
• src/auth/types.ts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
コミット 2/3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
メッセージ: test: add comprehensive tests for authentication system
含まれるファイル:
• tests/auth.test.ts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
コミット 3/3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
メッセージ: docs: add authentication system documentation
含まれるファイル:
• docs/authentication.md
この分割案でコミットを実行しますか? (y/n/edit):
```
### 実行時の選択肢
- `y` : 提案されたコミット分割で実行
- `n` : キャンセル
- `edit` : コミットメッセージを個別に編集
- `merge <番号 1> <番号 2>` : 指定したコミットをマージ
- `split <番号>` : 指定したコミットをさらに分割
### Dry Run モード
```bash
$ /semantic-commit --dry-run
変更分析中... (DRY RUN)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[コミット分割提案の表示]
DRY RUN モード: 実際のコミットは実行されません
💡 実行する場合は --dry-run オプションを除いて再実行してください
```
### スマート分析機能
#### 1. プロジェクト構造の理解
- `package.json`, `Cargo.toml`, `pom.xml` などからプロジェクト種別を判定
- フォルダ構造から機能単位を推測
#### 2. 変更パターンの認識
```bash
# バグ修正パターンの検出
- "fix", "bug", "error" などのキーワード
- 例外処理の追加
- 条件分岐の修正
# 新機能パターンの検出
- 新ファイル作成
- 新メソッド追加
- API エンドポイント追加
```
#### 3. 依存関係の分析
- インポート文の変更
- 型定義の追加/修正
- 設定ファイルとの関連性
### 技術的実装
#### Git 標準コマンドによる順次コミット実装
##### 1. 前処理: 現在の状態を保存
```bash
# 未ステージの変更がある場合は一旦リセット
git reset HEAD
git status --porcelain > /tmp/original_state.txt
# 作業ブランチの確認
CURRENT_BRANCH=$(git branch --show-current)
echo "作業中のブランチ: $CURRENT_BRANCH"
```
##### 2. グループ別の順次コミット実行
```bash
# 分割計画の読み込み
while IFS= read -r commit_plan; do
group_num=$(echo "$commit_plan" | cut -d':' -f1)
files=$(echo "$commit_plan" | cut -d':' -f2- | tr ' ' '\n')
echo "=== コミット $group_num の実行 ==="
# 該当ファイルのみをステージング
echo "$files" | while read file; do
if [ -f "$file" ]; then
git add "$file"
echo "ステージング: $file"
fi
done
# ステージング状態の確認
staged_files=$(git diff --staged --name-only)
if [ -z "$staged_files" ]; then
echo "警告: ステージングされたファイルがありません"
continue
fi
# コミットメッセージの生成 (LLM による分析)
commit_msg=$(generate_commit_message_for_staged_files)
# ユーザー確認
echo "提案コミットメッセージ: $commit_msg"
echo "ステージングされたファイル:"
echo "$staged_files"
read -p "このコミットを実行しますか? (y/n): " confirm
if [ "$confirm" = "y" ]; then
# コミット実行
git commit -m "$commit_msg"
echo "✅ コミット $group_num 完了"
else
# ステージングを取り消し
git reset HEAD
echo "❌ コミット $group_num をスキップ"
fi
done < /tmp/commit_plan.txt
```
##### 3. エラーハンドリングとロールバック
```bash
# プリコミットフック失敗時の処理
commit_with_retry() {
local commit_msg="$1"
local max_retries=2
local retry_count=0
while [ $retry_count -lt $max_retries ]; do
if git commit -m "$commit_msg"; then
echo "✅ コミット成功"
return 0
else
echo "❌ コミット失敗 (試行 $((retry_count + 1))/$max_retries)"
# プリコミットフックによる自動修正を取り込み
if git diff --staged --quiet; then
echo "プリコミットフックにより変更が自動修正されました"
git add -u
fi
retry_count=$((retry_count + 1))
fi
done
echo "❌ コミットに失敗しました。手動で確認してください。"
return 1
}
# 中断からの復旧
resume_from_failure() {
echo "中断されたコミット処理を検出しました"
echo "現在のステージング状態:"
git status --porcelain
read -p "処理を続行しますか? (y/n): " resume
if [ "$resume" = "y" ]; then
# 最後のコミット位置から再開
last_commit=$(git log --oneline -1 --pretty=format:"%s")
echo "最後のコミット: $last_commit"
else
# 完全リセット
git reset HEAD
echo "処理をリセットしました"
fi
}
```
##### 4. 完了後の検証
```bash
# 全変更がコミットされたかの確認
remaining_changes=$(git status --porcelain | wc -l)
if [ $remaining_changes -eq 0 ]; then
echo "✅ すべての変更がコミットされました"
else
echo "⚠️ 未コミットの変更が残っています:"
git status --short
fi
# コミット履歴の表示
echo "作成されたコミット:"
git log --oneline -n 10 --graph
```
##### 5. 自動プッシュの抑制
```bash
# 注意: 自動プッシュは行わない
echo "📝 注意: 自動プッシュは実行されません"
echo "必要に応じて以下のコマンドでプッシュしてください:"
echo " git push origin $CURRENT_BRANCH"
```
#### 分割アルゴリズムの詳細
##### ステップ 1: 初期分析
```bash
# 全変更ファイルの取得と分類
git diff HEAD --name-status | while read status file; do
echo "$status:$file"
done > /tmp/changes.txt
# 機能ディレクトリ別の変更統計
git diff HEAD --name-only | cut -d'/' -f1-2 | sort | uniq -c
```
##### ステップ 2: 機能境界による初期グループ化
```bash
# ディレクトリベースのグループ化
GROUPS=$(git diff HEAD --name-only | cut -d'/' -f1-2 | sort | uniq)
for group in $GROUPS; do
echo "=== グループ: $group ==="
git diff HEAD --name-only | grep "^$group" | head -10
done
```
##### ステップ 3: 変更内容の類似性分析
```bash
# 各ファイルの変更タイプを分析
git diff HEAD --name-only | while read file; do
# 新規関数/クラス追加の検出
NEW_FUNCTIONS=$(git diff HEAD -- "$file" | grep -c '^+.*function\|^+.*class\|^+.*def ')
# バグ修正パターンの検出
BUG_FIXES=$(git diff HEAD -- "$file" | grep -c '^+.*fix\|^+.*bug\|^-.*error')
# テストファイルかの判定
if [[ "$file" =~ test|spec ]]; then
echo "$file: TEST"
elif [ $NEW_FUNCTIONS -gt 0 ]; then
echo "$file: FEAT"
elif [ $BUG_FIXES -gt 0 ]; then
echo "$file: FIX"
else
echo "$file: REFACTOR"
fi
done
```
##### ステップ 4: 依存関係による調整
```bash
# インポート関係の分析
git diff HEAD | grep -E '^[+-].*import|^[+-].*from.*import' | \
while read line; do
echo "$line" | sed 's/^[+-]//' | awk '{print $2}'
done | sort | uniq > /tmp/imports.txt
# 関連ファイルのグループ化
git diff HEAD --name-only | while read file; do
basename=$(basename "$file" .js .ts .py)
related=$(git diff HEAD --name-only | grep "$basename" | grep -v "^$file$")
if [ -n "$related" ]; then
echo "関連ファイル群: $file <-> $related"
fi
done
```
##### ステップ 5: コミットサイズの最適化
```bash
# グループサイズの調整
MAX_FILES_PER_COMMIT=8
current_group=1
file_count=0
git diff HEAD --name-only | while read file; do
if [ $file_count -ge $MAX_FILES_PER_COMMIT ]; then
current_group=$((current_group + 1))
file_count=0
fi
echo "コミット $current_group: $file"
file_count=$((file_count + 1))
done
```
##### ステップ 6: 最終グループ決定
```bash
# 分割結果の検証
for group in $(seq 1 $current_group); do
files=$(grep "コミット $group:" /tmp/commit_plan.txt | cut -d':' -f2-)
lines=$(echo "$files" | xargs git diff HEAD -- | wc -l)
echo "コミット $group: $(echo "$files" | wc -w) ファイル, $lines 行変更"
done
```
### Conventional Commits 準拠
#### 基本形式
```text
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
#### 標準タイプ
**必須タイプ**:
- `feat`: 新機能 (ユーザーに見える機能追加)
- `fix`: バグ修正
**任意タイプ**:
- `build`: ビルドシステムや外部依存関係の変更
- `chore`: その他の変更 (リリースに影響しない)
- `ci`: CI 設定ファイルやスクリプトの変更
- `docs`: ドキュメントのみの変更
- `style`: コードの意味に影響しない変更 (空白、フォーマット、セミコロンなど)
- `refactor`: バグ修正や機能追加を伴わないコード変更
- `perf`: パフォーマンス改善
- `test`: テストの追加や修正
#### スコープ (任意)
変更の影響範囲を示す:
```text
feat(api): add user authentication endpoint
fix(ui): resolve button alignment issue
docs(readme): update installation instructions
```
#### Breaking Change
API の破壊的変更がある場合:
```text
feat!: change user API response format
BREAKING CHANGE: user response now includes additional metadata
```
または
```text
feat(api)!: change authentication flow
```
#### プロジェクト規約の自動検出
**重要**: プロジェクト独自の規約が存在する場合は、それを優先します。
##### 1. CommitLint 設定の確認
以下のファイルから設定を自動検出:
- `commitlint.config.js`
- `commitlint.config.mjs`
- `commitlint.config.cjs`
- `commitlint.config.ts`
- `.commitlintrc.js`
- `.commitlintrc.json`
- `.commitlintrc.yml`
- `.commitlintrc.yaml`
- `package.json``commitlint` セクション
```bash
# 設定ファイル例の確認
cat commitlint.config.mjs
cat .commitlintrc.json
grep -A 10 '"commitlint"' package.json
```
##### 2. カスタムタイプの検出
プロジェクト独自のタイプ例:
```javascript
// commitlint.config.mjs
export default {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [
2,
"always",
[
"feat",
"fix",
"docs",
"style",
"refactor",
"test",
"chore",
"wip", // 作業中
"hotfix", // 緊急修正
"release", // リリース
"deps", // 依存関係更新
"config", // 設定変更
],
],
},
};
```
##### 3. 言語設定の検出
```javascript
// プロジェクトが日本語メッセージを使用する場合
export default {
rules: {
"subject-case": [0], // 日本語対応のため無効化
"subject-max-length": [2, "always", 72], // 日本語は文字数制限を調整
},
};
```
#### 自動分析の流れ
1. **設定ファイル検索**
```bash
find . -name "commitlint.config.*" -o -name ".commitlintrc.*" | head -1
```
2. **既存コミット分析**
```bash
git log --oneline -50 --pretty=format:"%s"
```
3. **使用タイプ統計**
```bash
git log --oneline -100 --pretty=format:"%s" | \
grep -oE '^[a-z]+(\([^)]+\))?' | \
sort | uniq -c | sort -nr
```
#### プロジェクト規約の例
##### Angular スタイル
```text
feat(scope): add new feature
fix(scope): fix bug
docs(scope): update documentation
```
##### Gitmoji 併用スタイル
```text
✨ feat: add user registration
🐛 fix: resolve login issue
📚 docs: update API docs
```
##### 日本語プロジェクト
```text
feat: ユーザー登録機能を追加
fix: ログイン処理のバグを修正
docs: API ドキュメントを更新
```
### 言語判定
このコマンドで完結する言語判定ロジック:
1. **CommitLint 設定**から言語設定を確認
```bash
# subject-case ルールが無効化されている場合は日本語と判定
grep -E '"subject-case".*\[0\]|subject-case.*0' commitlint.config.*
```
2. **git log 分析**による自動判定
```bash
# 最近 20 コミットの言語を分析
git log --oneline -20 --pretty=format:"%s" | \
grep -E '^[あ-ん]|[ア-ン]|[一-龯]' | wc -l
# 50% 以上が日本語なら日本語モード
```
3. **プロジェクトファイル**の言語設定
```bash
# README.md の言語確認
head -10 README.md | grep -E '^[あ-ん]|[ア-ン]|[一-龯]' | wc -l
# package.json の description 確認
grep -E '"description".*[あ-ん]|[ア-ン]|[一-龯]' package.json
```
4. **変更ファイル内**のコメント・文字列分析
```bash
# 変更されたファイルのコメント言語を確認
git diff HEAD | grep -E '^[+-].*//.*[あ-ん]|[ア-ン]|[一-龯]' | wc -l
```
#### 判定アルゴリズム
```bash
# 言語判定スコア計算
JAPANESE_SCORE=0
# 1. CommitLint 設定 (+3 点)
if grep -q '"subject-case".*\[0\]' commitlint.config.* 2>/dev/null; then
JAPANESE_SCORE=$((JAPANESE_SCORE + 3))
fi
# 2. git log 分析 (最大+2 点)
JAPANESE_COMMITS=$(git log --oneline -20 --pretty=format:"%s" | \
grep -cE '[あ-ん]|[ア-ン]|[一-龯]' 2>/dev/null || echo 0)
if [ $JAPANESE_COMMITS -gt 10 ]; then
JAPANESE_SCORE=$((JAPANESE_SCORE + 2))
elif [ $JAPANESE_COMMITS -gt 5 ]; then
JAPANESE_SCORE=$((JAPANESE_SCORE + 1))
fi
# 3. README.md 確認 (+1 点)
if head -5 README.md 2>/dev/null | grep -qE '[あ-ん]|[ア-ン]|[一-龯]'; then
JAPANESE_SCORE=$((JAPANESE_SCORE + 1))
fi
# 4. 変更ファイル内容確認 (+1 点)
if git diff HEAD 2>/dev/null | grep -qE '^[+-].*[あ-ん]|[ア-ン]|[一-龯]'; then
JAPANESE_SCORE=$((JAPANESE_SCORE + 1))
fi
# 判定: 3 点以上で日本語モード
if [ $JAPANESE_SCORE -ge 3 ]; then
LANGUAGE="ja"
else
LANGUAGE="en"
fi
```
### 設定ファイル自動読み込み
#### 実行時の動作
コマンド実行時に以下の順序で設定を確認:
1. **CommitLint 設定ファイルの検索**
```bash
# 以下の順序で検索し、最初に見つかったファイルを使用
commitlint.config.mjs
commitlint.config.js
commitlint.config.cjs
commitlint.config.ts
.commitlintrc.js
.commitlintrc.json
.commitlintrc.yml
.commitlintrc.yaml
package.json (commitlint セクション)
```
2. **設定内容の解析**
- 使用可能なタイプの一覧を抽出
- スコープの制限があるかを確認
- メッセージ長制限の取得
- 言語設定の確認
3. **既存コミット履歴の分析**
```bash
# 最近のコミットから使用パターンを学習
git log --oneline -100 --pretty=format:"%s" | \
head -20
```
#### 設定例の分析
**標準的な commitlint.config.mjs**:
```javascript
export default {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [
2,
"always",
["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore"],
],
"scope-enum": [2, "always", ["api", "ui", "core", "auth", "db"]],
},
};
```
**日本語対応の設定**:
```javascript
export default {
extends: ["@commitlint/config-conventional"],
rules: {
"subject-case": [0], // 日本語のため無効化
"subject-max-length": [2, "always", 72],
"type-enum": [
2,
"always",
["feat", "fix", "docs", "style", "refactor", "test", "chore"],
],
},
};
```
**カスタムタイプを含む設定**:
```javascript
export default {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [
2,
"always",
[
"feat",
"fix",
"docs",
"style",
"refactor",
"test",
"chore",
"wip", // Work in Progress
"hotfix", // 緊急修正
"release", // リリース準備
"deps", // 依存関係更新
"config", // 設定変更
],
],
},
};
```
#### フォールバック動作
設定ファイルが見つからない場合:
1. **git log 分析**による自動推測
```bash
# 最近 100 コミットからタイプを抽出
git log --oneline -100 --pretty=format:"%s" | \
grep -oE '^[a-z]+(\([^)]+\))?' | \
sort | uniq -c | sort -nr
```
2. **Conventional Commits 標準**をデフォルト使用
```
feat, fix, docs, style, refactor, perf, test, chore, build, ci
```
3. **言語判定**
- 日本語コミットが 50% 以上 → 日本語モード
- その他 → 英語モード
### 前提条件
- Git リポジトリ内で実行
- 未コミットの変更が存在すること
- ステージングされた変更は一旦リセットされます
### 注意事項
- **自動プッシュなし**: コミット後の `git push` は手動実行
- **ブランチ作成なし**: 現在のブランチでコミット
- **バックアップ推奨**: 重要な変更前には `git stash` でバックアップ
### プロジェクト規約の優先度
コミットメッセージ生成時の優先度:
1. **CommitLint 設定** (最優先)
- `commitlint.config.*` ファイルの設定
- カスタムタイプやスコープの制限
- メッセージ長やケースの制限
2. **既存コミット履歴** (第 2 優先)
- 実際に使用されているタイプの統計
- メッセージの言語 (日本語/英語)
- スコープの使用パターン
3. **プロジェクト種別** (第 3 優先)
- `package.json` → Node.js プロジェクト
- `Cargo.toml` → Rust プロジェクト
- `pom.xml` → Java プロジェクト
4. **Conventional Commits 標準** (フォールバック)
- 設定が見つからない場合の標準動作
#### 規約検出の実例
**Monorepo での scope 自動検出**:
```bash
# packages/ フォルダから scope を推測
ls packages/ | head -10
# → api, ui, core, auth などを scope として提案
```
**フレームワーク固有の規約**:
```javascript
// Angular プロジェクトの場合
{
'scope-enum': [2, 'always', [
'animations', 'common', 'core', 'forms', 'http', 'platform-browser',
'platform-server', 'router', 'service-worker', 'upgrade'
]]
}
// React プロジェクトの場合
{
'scope-enum': [2, 'always', [
'components', 'hooks', 'utils', 'types', 'styles', 'api'
]]
}
```
**企業・チーム固有の規約**:
```javascript
// 日本の企業でよく見られるパターン
{
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore',
'wip', // 作業中 (プルリクエスト用)
'hotfix', // 緊急修正
'release' // リリース準備
]],
'subject-case': [0], // 日本語対応
'subject-max-length': [2, 'always', 72] // 日本語は長めに設定
}
```
### ベストプラクティス
1. **プロジェクト規約の尊重**: 既存の設定やパターンに従う
2. **小さな変更単位**: 1 つのコミットは 1 つの論理的変更
3. **明確なメッセージ**: 何を変更したかが明確
4. **関連性の重視**: 機能的に関連するファイルをグループ化
5. **テストの分離**: テストファイルは別コミットに
6. **設定ファイルの活用**: CommitLint を導入してチーム全体で規約を統一
### 実際の分割例 (Before/After)
#### 例 1: 大規模な認証システム追加
**Before(1 つの巨大なコミット):**
```bash
# 変更されたファイル (15 ファイル、850 行変更)
src/auth/login.js # 新規作成
src/auth/register.js # 新規作成
src/auth/password.js # 新規作成
src/auth/types.js # 新規作成
src/api/auth-routes.js # 新規作成
src/middleware/auth.js # 新規作成
src/database/migrations/001_users.sql # 新規作成
src/database/models/user.js # 新規作成
tests/auth/login.test.js # 新規作成
tests/auth/register.test.js # 新規作成
tests/api/auth-routes.test.js # 新規作成
docs/authentication.md # 新規作成
package.json # 依存関係追加
README.md # 使用方法追加
.env.example # 環境変数例追加
# 従来の問題のあるコミット
feat: implement complete user authentication system with login, registration, password reset, API routes, database models, tests and documentation
```
**After(意味のある 5 つのコミットに分割):**
```bash
# コミット 1: データベース基盤
feat(db): add user model and authentication schema
含まれるファイル:
- src/database/migrations/001_users.sql
- src/database/models/user.js
- src/auth/types.js
理由: データベース構造は他の機能の基盤となるため最初にコミット
# コミット 2: 認証ロジック
feat(auth): implement core authentication functionality
含まれるファイル:
- src/auth/login.js
- src/auth/register.js
- src/auth/password.js
- src/middleware/auth.js
理由: 認証の核となるビジネスロジックを一括でコミット
# コミット 3: API エンドポイント
feat(api): add authentication API routes
含まれるファイル:
- src/api/auth-routes.js
理由: API レイヤーは認証ロジックに依存するため後でコミット
# コミット 4: 包括的なテスト
test(auth): add comprehensive authentication tests
含まれるファイル:
- tests/auth/login.test.js
- tests/auth/register.test.js
- tests/api/auth-routes.test.js
理由: 実装完了後にテストを一括追加
# コミット 5: 設定とドキュメント
docs(auth): add authentication documentation and configuration
含まれるファイル:
- docs/authentication.md
- package.json
- README.md
- .env.example
理由: ドキュメントと設定は最後にまとめてコミット
```
#### 例 2: バグ修正とリファクタリングの混在
**Before(混在した問題のあるコミット):**
```bash
# 変更されたファイル (8 ファイル、320 行変更)
src/user/service.js # バグ修正 + リファクタリング
src/user/validator.js # 新規作成 (リファクタリング)
src/auth/middleware.js # バグ修正
src/api/user-routes.js # バグ修正 + エラーハンドリング改善
tests/user.test.js # テスト追加
tests/auth.test.js # バグ修正テスト追加
docs/user-api.md # ドキュメント更新
package.json # 依存関係更新
# 問題のあるコミット
fix: resolve user validation bugs and refactor validation logic with improved error handling
```
**After(種別別に 3 つのコミットに分割):**
```bash
# コミット 1: 緊急バグ修正
fix: resolve user validation and authentication bugs
含まれるファイル:
- src/user/service.js(バグ修正部分のみ)
- src/auth/middleware.js
- tests/auth.test.js(バグ修正テストのみ)
理由: 本番環境に影響するバグは最優先で修正
# コミット 2: バリデーションロジックのリファクタリング
refactor: extract and improve user validation logic
含まれるファイル:
- src/user/service.js(リファクタリング部分)
- src/user/validator.js
- src/api/user-routes.js
- tests/user.test.js
理由: 構造改善は機能単位でまとめてコミット
# コミット 3: ドキュメントと依存関係更新
chore: update documentation and dependencies
含まれるファイル:
- docs/user-api.md
- package.json
理由: 開発環境の整備は最後にまとめてコミット
```
#### 例 3: 複数機能の同時開発
**Before(機能横断の巨大コミット):**
```bash
# 変更されたファイル (12 ファイル、600 行変更)
src/user/profile.js # 新機能 A
src/user/avatar.js # 新機能 A
src/notification/email.js # 新機能 B
src/notification/sms.js # 新機能 B
src/api/profile-routes.js # 新機能 A 用 API
src/api/notification-routes.js # 新機能 B 用 API
src/dashboard/widgets.js # 新機能 C
src/dashboard/charts.js # 新機能 C
tests/profile.test.js # 新機能 A 用テスト
tests/notification.test.js # 新機能 B 用テスト
tests/dashboard.test.js # 新機能 C 用テスト
package.json # 全機能の依存関係
# 問題のあるコミット
feat: add user profile management, notification system and dashboard widgets
```
**After(機能別に 4 つのコミットに分割):**
```bash
# コミット 1: ユーザープロフィール機能
feat(profile): add user profile management
含まれるファイル:
- src/user/profile.js
- src/user/avatar.js
- src/api/profile-routes.js
- tests/profile.test.js
理由: プロフィール機能は独立した機能単位
# コミット 2: 通知システム
feat(notification): implement email and SMS notifications
含まれるファイル:
- src/notification/email.js
- src/notification/sms.js
- src/api/notification-routes.js
- tests/notification.test.js
理由: 通知機能は独立した機能単位
# コミット 3: ダッシュボードウィジェット
feat(dashboard): add interactive widgets and charts
含まれるファイル:
- src/dashboard/widgets.js
- src/dashboard/charts.js
- tests/dashboard.test.js
理由: ダッシュボード機能は独立した機能単位
# コミット 4: 依存関係とインフラ更新
chore: update dependencies for new features
含まれるファイル:
- package.json
理由: 共通の依存関係更新は最後にまとめて
```
### 分割効果の比較
| 項目 | Before(巨大コミット) | After(適切な分割) |
| -------------- | ----------------------------- | --------------------------------------- |
| **レビュー性** | ❌ 非常に困難 | ✅ 各コミットが小さくレビュー可能 |
| **バグ追跡** | ❌ 問題箇所の特定が困難 | ✅ 問題のあるコミットを即座に特定 |
| **リバート** | ❌ 全体をリバートする必要 | ✅ 問題部分のみをピンポイントでリバート |
| **並行開発** | ❌ コンフリクトが発生しやすい | ✅ 機能別でマージが容易 |
| **デプロイ** | ❌ 全機能を一括デプロイ | ✅ 段階的なデプロイが可能 |
### トラブルシューティング
#### コミット失敗時
- プリコミットフックの確認
- 依存関係の解決
- 個別ファイルでの再試行
#### 分割が適切でない場合
- `--max-commits` オプションで調整
- 手動での `edit` モード使用
- より細かい単位での再実行