Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:23:35 +08:00
commit 0fe2638c61
150 changed files with 37511 additions and 0 deletions

381
commands/commit-split.md Normal file
View File

@@ -0,0 +1,381 @@
# コミット分割コマンド
Gitの差分をもとに適切にコミットを分割します。ファイル単位や機能単位で論理的にコミットを分けることで、レビューしやすく意味のあるコミット履歴を作成します。
## 使用方法
```bash
/commit-split [ベースブランチ] [分割方式]
```
### パラメータ
- `ベースブランチ`: 比較対象のブランチ(省略時は`master`または`main`を自動検出)
- `分割方式`: `file`(ファイル単位)、`feature`(機能単位)、`interactive`(インタラクティブ)
## 処理手順
1. 現在の変更状況を確認
2. 差分の分析と分割方針の決定
3. インタラクティブな分割実行
4. 各コミットの作成と確認
## 実装
### ステップ1: 初期状態の確認
```bash
# 作業ディレクトリの状態を確認
echo "📊 現在の作業状況を確認中..."
git status --porcelain
# ステージされていない変更があるかチェック
UNSTAGED_CHANGES=$(git diff --name-only)
STAGED_CHANGES=$(git diff --cached --name-only)
if [ -n "$UNSTAGED_CHANGES" ] || [ -n "$STAGED_CHANGES" ]; then
echo "⚠️ 未コミットの変更があります"
echo "📝 ステージされていない変更: $(echo "$UNSTAGED_CHANGES" | wc -l) ファイル"
echo "📝 ステージされた変更: $(echo "$STAGED_CHANGES" | wc -l) ファイル"
else
echo "✅ 作業ディレクトリはクリーンです"
exit 0
fi
```
### ステップ2: ベースブランチの決定
```bash
# ベースブランチの自動検出または指定
BASE_BRANCH="${1:-}"
if [ -z "$BASE_BRANCH" ]; then
if git show-ref --verify --quiet refs/heads/master; then
BASE_BRANCH="master"
elif git show-ref --verify --quiet refs/heads/main; then
BASE_BRANCH="main"
else
echo "❌ ベースブランチを特定できません。明示的に指定してください。"
exit 1
fi
fi
echo "🎯 ベースブランチ: $BASE_BRANCH"
# ベースブランチとの差分を確認
CURRENT_BRANCH=$(git branch --show-current)
echo "🌿 現在のブランチ: $CURRENT_BRANCH"
```
### ステップ3: 差分の分析
```bash
# 変更されたファイルの一覧と統計
echo "📈 差分の分析中..."
CHANGED_FILES=$(git diff --name-only $BASE_BRANCH..HEAD 2>/dev/null || git diff --name-only)
if [ -z "$CHANGED_FILES" ]; then
echo "📝 ベースブランチとの差分がありません"
# 作業ディレクトリの変更のみ処理
CHANGED_FILES=$(git diff --name-only)
if [ -z "$CHANGED_FILES" ]; then
CHANGED_FILES=$(git diff --cached --name-only)
fi
fi
echo "📁 変更されたファイル一覧:"
echo "$CHANGED_FILES" | nl
# ファイルタイプ別の分類
DOCS_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(md|txt|rst)$' || true)
CONFIG_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(json|yaml|yml|toml|ini|conf)$' || true)
CODE_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(js|ts|py|go|rs|java|c|cpp|php|rb)$' || true)
TEST_FILES=$(echo "$CHANGED_FILES" | grep -E '(test|spec)\.' || true)
echo ""
echo "📊 ファイルタイプ別統計:"
[ -n "$DOCS_FILES" ] && echo "📖 ドキュメント: $(echo "$DOCS_FILES" | wc -l) ファイル"
[ -n "$CONFIG_FILES" ] && echo "⚙️ 設定ファイル: $(echo "$CONFIG_FILES" | wc -l) ファイル"
[ -n "$CODE_FILES" ] && echo "💻 コードファイル: $(echo "$CODE_FILES" | wc -l) ファイル"
[ -n "$TEST_FILES" ] && echo "🧪 テストファイル: $(echo "$TEST_FILES" | wc -l) ファイル"
```
### ステップ4: 分割方式の決定
```bash
SPLIT_MODE="${2:-file}"
case "$SPLIT_MODE" in
"file")
echo "📂 ファイル単位での分割を実行します"
commit_by_file
;;
"feature")
echo "🎯 機能単位での分割を実行します"
commit_by_feature
;;
"interactive"|*)
echo "🤝 インタラクティブ分割を実行します"
commit_interactive
;;
esac
```
### ステップ5: ファイル単位分割の実装
```bash
commit_by_file() {
echo "$CHANGED_FILES" | while read -r file; do
if [ -n "$file" ]; then
echo ""
echo "📝 処理中: $file"
# ファイルの変更内容を表示
git diff --stat "$file" 2>/dev/null || git diff --cached --stat "$file" 2>/dev/null || true
# コミットメッセージの自動生成
FILE_EXT="${file##*.}"
DIR_NAME=$(dirname "$file")
FILE_NAME=$(basename "$file")
# ファイルタイプに基づいたプレフィックス
if echo "$file" | grep -q -E '\.(md|txt|rst)$'; then
PREFIX="docs"
elif echo "$file" | grep -q -E '\.(json|yaml|yml|toml|ini|conf)$'; then
PREFIX="config"
elif echo "$file" | grep -q -E '(test|spec)\.'; then
PREFIX="test"
else
PREFIX="feat"
fi
COMMIT_MSG="$PREFIX: update $FILE_NAME"
# 自動でコミット(確認なし)
echo "💬 提案されたコミットメッセージ: $COMMIT_MSG"
git add "$file"
git commit -m "$COMMIT_MSG"
echo "✅ コミット完了: $file"
fi
done
}
```
### ステップ6: 機能単位分割の実装
```bash
commit_by_feature() {
# ディレクトリ構造に基づいた機能別グループ化
echo "🔍 機能別にファイルをグループ化中..."
# ディレクトリごとにファイルをグループ化
DIRECTORIES=$(echo "$CHANGED_FILES" | xargs dirname | sort | uniq)
echo "$DIRECTORIES" | while read -r dir; do
if [ -n "$dir" ]; then
DIR_FILES=$(echo "$CHANGED_FILES" | grep "^$dir/")
if [ -n "$DIR_FILES" ]; then
echo ""
echo "📁 ディレクトリ: $dir"
echo "$DIR_FILES" | sed 's/^/ - /'
# ディレクトリ名に基づいたコミットメッセージ
case "$dir" in
"src"|"lib"|"app")
PREFIX="feat"
;;
"test"|"tests"|"__tests__")
PREFIX="test"
;;
"docs"|"doc")
PREFIX="docs"
;;
"config"|".github")
PREFIX="config"
;;
*)
PREFIX="update"
;;
esac
COMMIT_MSG="$PREFIX: update $dir module"
echo "💬 提案されたコミットメッセージ: $COMMIT_MSG"
echo "$DIR_FILES" | xargs git add
git commit -m "$COMMIT_MSG"
echo "✅ コミット完了: $dir"
fi
fi
done
}
```
### ステップ7: インタラクティブ分割の実装
```bash
commit_interactive() {
echo "🎮 自動モードでコミットを分割します"
# 現在の状態を確認
REMAINING_UNSTAGED=$(git diff --name-only)
REMAINING_STAGED=$(git diff --cached --name-only)
if [ -z "$REMAINING_UNSTAGED" ] && [ -z "$REMAINING_STAGED" ]; then
echo "📝 変更がありません"
return
fi
# 全ファイルをステージして一度にコミット
git add .
commit_staged_changes
echo "🎉 すべての変更が処理されました!"
}
select_files_for_staging() {
ALL_CHANGED=$(git status --porcelain | awk '{print $2}')
if [ -z "$ALL_CHANGED" ]; then
echo "📝 変更されたファイルがありません"
return
fi
echo "📁 変更されたファイル一覧:"
echo "$ALL_CHANGED" | nl
echo ""
# 全ファイルを自動でステージ
echo "$ALL_CHANGED" | while read -r file; do
if [ -n "$file" ]; then
git add "$file"
echo "✅ ステージ完了: $file"
fi
done
}
commit_staged_changes() {
STAGED=$(git diff --cached --name-only)
if [ -z "$STAGED" ]; then
echo "📦 ステージされた変更がありません"
return
fi
echo "📦 ステージされたファイル:"
echo "$STAGED" | sed 's/^/ - /'
echo ""
# 自動でコミット
commit_msg="update: staged changes"
git commit -m "$commit_msg"
echo "✅ コミット完了!"
}
show_diff_summary() {
echo "📊 変更サマリー:"
git diff --stat
echo ""
git diff --cached --stat
echo ""
# 詳細な差分を自動的に表示
echo "📖 詳細な差分:"
git diff
git diff --cached
}
auto_push_changes() {
# 現在のブランチ名を取得
CURRENT_BRANCH=$(git branch --show-current)
echo "📤 リモートブランチにプッシュ中..."
# リモートブランチが存在するかチェック
if git ls-remote --heads origin "$CURRENT_BRANCH" | grep -q "$CURRENT_BRANCH"; then
# リモートブランチが存在する場合は通常のpush
git push
if [ $? -eq 0 ]; then
echo "✅ プッシュ完了: $CURRENT_BRANCH"
else
echo "⚠️ プッシュでエラーが発生しました"
fi
else
# リモートブランチが存在しない場合は -u オプション付きでpush
git push -u origin "$CURRENT_BRANCH"
if [ $? -eq 0 ]; then
echo "✅ 新しいブランチを作成してプッシュ完了: $CURRENT_BRANCH"
else
echo "⚠️ プッシュでエラーが発生しました"
fi
fi
}
show_help() {
echo "📚 コミット分割ヘルプ"
echo ""
echo "🎯 目的: 大きな変更を論理的に分割して複数のコミットに分ける"
echo ""
echo "💡 推奨される分割方針:"
echo " - 📁 ファイルタイプ別(設定、ドキュメント、コード、テスト)"
echo " - 🎯 機能別(新機能、バグ修正、リファクタリング)"
echo " - 📦 影響範囲別フロントエンド、バックエンド、DB"
echo ""
echo "🔧 便利なGitコマンド:"
echo " - git add -p : パッチ単位での選択的ステージング"
echo " - git diff --cached : ステージされた変更の確認"
echo " - git reset <file> : ファイルのアンステージ"
echo " - git status : 現在の状態確認"
echo ""
echo "📤 プッシュ機能:"
echo " - 各コミット後に個別でプッシュするか選択可能"
echo " - 最終処理で全てのコミットを一括プッシュ"
}
```
### ステップ8: 完了処理とプッシュ
```bash
# 最終確認と統計
echo ""
echo "🎉 コミット分割が完了しました!"
echo ""
echo "📈 作成されたコミット:"
git log --oneline -10
echo ""
echo "📤 自動プッシュを実行します..."
# 現在のブランチ名を取得
CURRENT_BRANCH=$(git branch --show-current)
# リモートブランチが存在するかチェック
if git ls-remote --heads origin "$CURRENT_BRANCH" | grep -q "$CURRENT_BRANCH"; then
# リモートブランチが存在する場合は通常のpush
git push
echo "✅ プッシュ完了: $CURRENT_BRANCH"
else
# リモートブランチが存在しない場合は -u オプション付きでpush
git push -u origin "$CURRENT_BRANCH"
echo "✅ 新しいブランチを作成してプッシュ完了: $CURRENT_BRANCH"
fi
echo ""
echo "🚀 すべてのコミットがリモートに反映されました!"
```
## 重要なルール
- **段階的なコミット**: 関連する変更をまとめて、レビューしやすい単位でコミット
- **意味のあるメッセージ**: 各コミットが何を変更したかを明確に記述
- **ファイルタイプの考慮**: 設定ファイル、ドキュメント、コード、テストを適切に分離
- **レビュー性の向上**: 1つのコミットで1つの論理的変更を実現
- **自動プッシュ**: 各コミット後にプッシュ選択可能、最終的に全コミットをリモートに反映
## 使用例
### ファイル単位での分割
```bash
/commit-split master file
```
### 機能単位での分割
```bash
/commit-split main feature
```
### インタラクティブ分割
```bash
/commit-split
```
## 注意事項
- 実行前に重要な変更はバックアップを取ってください
- `git add -p` を使用する際は、パッチの内容をよく確認してください
- 各コミット後にプッシュするかどうかを選択できます
- 最終的にすべてのコミットがリモートに反映されます
- リモートにプッシュ済みのコミットは分割しないでください