---
description: Phase 3 - Smart commit with EF Core migration validation
agent: gitflow-commit
model: sonnet
args: [message]
---

# Phase 3: COMMIT - Migration-aware commits

You are an expert in GitFlow and EF Core. Manage commits with validation of .NET migrations.

> **CLAUDE INSTRUCTION:** The `AskUserQuestion({...})` blocks below are instructions for using the `AskUserQuestion` tool **interactively**. You MUST execute the tool with these parameters to get the user's response BEFORE continuing. DO NOT display this code - WAIT for the response.

**Argument:** `$ARGUMENTS` = commit message (optional, generated if absent)

---

## ETAPE 0: GARDE-FOUS PRE-COMMIT

> **PROTECTION:** Verifications de securite AVANT toute operation de commit.

### 0.1 Protection des branches

```bash
CURRENT=$(git rev-parse --abbrev-ref HEAD)

# ═══════════════════════════════════════════════════════════════
# BLOCAGE: Commit direct sur main
# ═══════════════════════════════════════════════════════════════
if [[ "$CURRENT" == "main" ]]; then
  echo ""
  echo "╔══════════════════════════════════════════════════════════════════════════════╗"
  echo "║  ⛔ COMMIT BLOQUE - BRANCHE PROTEGEE                                          ║"
  echo "╠══════════════════════════════════════════════════════════════════════════════╣"
  echo "║  Vous etes sur 'main' - les commits directs ne sont pas autorises.           ║"
  echo "║                                                                              ║"
  echo "║  GitFlow interdit les commits directs sur main car:                          ║"
  echo "║  - main represente le code en production                                     ║"
  echo "║  - Les changements doivent passer par release ou hotfix                      ║"
  echo "║                                                                              ║"
  echo "║  ALTERNATIVES:                                                               ║"
  echo "║  → Correction urgente?   /gitflow:10-start hotfix <nom>                      ║"
  echo "║  → Nouvelle release?     /gitflow:10-start release                           ║"
  echo "╚══════════════════════════════════════════════════════════════════════════════╝"
  echo ""
  exit 1
fi

# ═══════════════════════════════════════════════════════════════
# AVERTISSEMENT: Commit direct sur develop
# ═══════════════════════════════════════════════════════════════
if [[ "$CURRENT" == "develop" ]]; then
  echo ""
  echo "╔══════════════════════════════════════════════════════════════════════════════╗"
  echo "║  ⚠️  ATTENTION - COMMIT SUR DEVELOP                                           ║"
  echo "╠══════════════════════════════════════════════════════════════════════════════╣"
  echo "║  Vous etes sur 'develop' - les commits directs sont deconseilles.            ║"
  echo "║                                                                              ║"
  echo "║  GitFlow recommande de passer par des branches feature car:                  ║"
  echo "║  - Permet la review avant integration                                        ║"
  echo "║  - Isole les changements en cours                                            ║"
  echo "║  - Facilite le rollback si necessaire                                        ║"
  echo "║                                                                              ║"
  echo "║  ALTERNATIVE RECOMMANDEE:                                                    ║"
  echo "║  → /gitflow:10-start feature <nom>                                           ║"
  echo "╚══════════════════════════════════════════════════════════════════════════════╝"
  echo ""
fi
```

**Si sur develop, demander confirmation:**
```javascript
if (CURRENT === "develop") {
  AskUserQuestion({
    questions: [{
      question: "Voulez-vous vraiment committer directement sur develop ?",
      header: "Confirm",
      options: [
        { label: "Non, creer une feature", description: "Recommande - /gitflow:10-start feature" },
        { label: "Oui, commit direct", description: "Non recommande - bypass GitFlow" }
      ],
      multiSelect: false
    }]
  })

  if (response === "Non, creer une feature") {
    console.log("→ Lancez: /gitflow:10-start feature <nom>")
    exit(0)
  }
}
```

### 0.2 Verification synchronisation

```bash
# Verifier si la branche est a jour avec le remote
git fetch origin --quiet 2>/dev/null

BEHIND=$(git rev-list --count HEAD..origin/$CURRENT 2>/dev/null || echo "0")

if [ "$BEHIND" -gt 0 ]; then
  echo ""
  echo "┌──────────────────────────────────────────────────────────────────────────────┐"
  echo "│  ⚠️  BRANCHE EN RETARD                                                        │"
  echo "├──────────────────────────────────────────────────────────────────────────────┤"
  echo "│  Votre branche est $BEHIND commits en retard par rapport au remote.          │"
  echo "│                                                                              │"
  echo "│  RECOMMANDATION:                                                             │"
  echo "│  → Synchronisez d'abord: git pull --rebase origin $CURRENT                   │"
  echo "│  → Ou utilisez: /gitflow:13-sync                                             │"
  echo "└──────────────────────────────────────────────────────────────────────────────┘"
  echo ""
fi
```

**Si en retard, demander synchronisation:**
```javascript
if (BEHIND > 0) {
  AskUserQuestion({
    questions: [{
      question: `Votre branche est ${BEHIND} commits en retard. Synchroniser ?`,
      header: "Sync",
      options: [
        { label: "Oui, synchroniser", description: "git pull --rebase (Recommande)" },
        { label: "Non, continuer", description: "Commit sans sync (risque de conflit au push)" }
      ],
      multiSelect: false
    }]
  })

  if (response === "Oui, synchroniser") {
    // Executer git pull --rebase
    result = exec("git pull --rebase origin " + CURRENT)
    if (result.exitCode !== 0) {
      console.log("Conflits detectes. Resolvez-les puis relancez /gitflow:3-commit")
      exit(1)
    }
  }
}
```

### 0.3 Verification working directory

```bash
# Verifier s'il y a des fichiers a committer
STAGED=$(git diff --cached --name-only | wc -l)
MODIFIED=$(git diff --name-only | wc -l)
UNTRACKED=$(git ls-files --others --exclude-standard | wc -l)

if [ "$STAGED" -eq 0 ] && [ "$MODIFIED" -eq 0 ] && [ "$UNTRACKED" -eq 0 ]; then
  echo ""
  echo "✅ Rien a committer - working directory propre"
  echo ""
  exit 0
fi

# Afficher resume
echo ""
echo "FICHIERS DETECTES:"
echo "  Staged:    $STAGED"
echo "  Modified:  $MODIFIED"
echo "  Untracked: $UNTRACKED"
echo ""
```

---

## Workflow

### 1. Analyze files

- Staged files
- Modified files not staged
- Untracked files
- Detect migration files in each category

### 2. Validate migrations

A valid EF Core migration = **3 files** :
- `{Timestamp}_{Name}.cs` - Main migration
- `{Timestamp}_{Name}.Designer.cs` - Metadata
- `{Context}ModelSnapshot.cs` - Model state

**Checks:**
- All 3 files are present
- Build compiles (`dotnet build`)
- No ModelSnapshot conflicts with develop

### 3. ⚠️ SAFETY CHECK - Destructive operations

**BLOCKING** - Scan migrations for dangerous operations :

```bash
# Patterns to detect in migration .cs files
grep -n "DropTable\|DropColumn\|DropIndex\|DropForeignKey\|DeleteData" {migration}.cs
grep -n "migrationBuilder.Sql" {migration}.cs | grep -i "DELETE\|DROP\|TRUNCATE"
```

**If detected :**

```
╔══════════════════════════════════════════════════════════╗
║  ⛔ DESTRUCTIVE OPERATIONS DETECTED                       ║
╠══════════════════════════════════════════════════════════╣
║  File: {migration}.cs                                    ║
║  Line {X}: DropTable("Users")                            ║
║  Line {Y}: DropColumn("Email", "Customers")              ║
╠══════════════════════════════════════════════════════════╣
║  RISKS:                                                  ║
║  - Irreversible data loss                                ║
║  - Verify that you have a BACKUP                         ║
╚══════════════════════════════════════════════════════════╝
```

**Actions:**
1. Display detailed alert (file, line, operation)
2. Request explicit confirmation: "Do you confirm? (yes/no)"
3. If "no" → Cancel commit
4. If "yes" → Log in [.claude/gitflow/logs/](.claude/gitflow/logs/)`dangerous-migrations.json`
5. Continue commit

**Dangerous patterns:**

| Pattern | Risk | Level |
|---------|------|-------|
| `DropTable` | Delete entire table | CRITICAL |
| `DropColumn` | Data loss in column | CRITICAL |
| `DeleteData` | Delete rows | CRITICAL |
| `DropForeignKey` | Break integrity | HIGH |
| `DropIndex` | Performance impact | MEDIUM |
| `Sql("DELETE...")` | Raw destructive SQL | CRITICAL |
| `Sql("DROP...")` | Raw destructive SQL | CRITICAL |
| `Sql("TRUNCATE...")` | Empty table | CRITICAL |

### 4. Classify commit

| Files | Type | Prefix |
|-------|------|--------|
| Migrations only | migration | `db(migrations):` |
| Migrations + code | mixed | `feat:` or `fix:` |
| Code without migration | code | Based on branch type |
| Config/docs | chore | `chore:` |

### 5. Generate message (if absent)

**Migration:**
```
db(migrations): {action} {description}

Migration: {MigrationName}
Tables: {CREATE|ALTER|DROP} {tables}
Context: {DbContext}
```

**Mixed:**
```
feat({scope}): {description}

- {changes}
Migrations: {list}
```

### 6. Execute commit

- Add missing migration files if necessary
- Verify one last time
- Commit with message

### 7. Post-commit

- Verify no migration files are left uncommitted
- Display summary

### 8. Automatic push (based on config)

Read config: `.claude/gitflow/config.json` → `workflow.push.afterCommit`

**Worktree detection:**
```bash
# If git-common-dir != .git → it's a worktree
COMMON_DIR=$(git rev-parse --git-common-dir 2>/dev/null)
if [[ "$COMMON_DIR" != ".git" && "$COMMON_DIR" != "." ]]; then
  IS_WORKTREE=true
fi
```

**Push logic:**

| Config `afterCommit` | Worktree | Action |
|---------------------|----------|--------|
| `worktree` | Yes | Automatic push |
| `worktree` | No | Ask user |
| `always` | - | Automatic push |
| `ask` | - | Ask user |
| `never` | - | Do not push |

**If user is asked:**
```
AskUserQuestion({
  questions: [{
    question: "Do you want to push this commit?",
    header: "Push",
    options: [
      { label: "Yes, push now", description: "git push origin <branch>" },
      { label: "No, later", description: "Local commit only" }
    ],
    multiSelect: false
  }]
})
```

**Execute push:**
```bash
git push origin $(git branch --show-current)
```

**Push error handling:**
- If remote not configured → Skip with message
- If rebase necessary → Warn and suggest:
  ```
  /gitflow:4-plan rebase
  ```
- If branch protected → Warn (PR required)

---

## Common errors

| Error | Solution |
|-------|----------|
| ModelSnapshot missing | Add the file |
| Designer missing | Add the file |
| Build fails | `dotnet ef migrations remove` + fix |
| Conflict detected | Rebase first |
| **Destructive operation** | Confirm or modify migration |

---

## Resume

**Afficher un resume apres le commit:**

```
═══════════════════════════════════════════════════════════════════════════════
                         COMMIT CRÉÉ
═══════════════════════════════════════════════════════════════════════════════

COMMIT DETAILS
───────────────────────────────────────────────────────────────────────────────
  • Branche:   {branch_name}
  • Hash:      {commit_hash_short}
  • Message:   {commit_message}
  • Fichiers:  {N} fichiers modifiés

FICHIERS INCLUS
───────────────────────────────────────────────────────────────────────────────
  {type_icon} {file_1}
  {type_icon} {file_2}
  {type_icon} {file_3}
  ... ({N} fichiers au total)

WORKFLOW STATUT
───────────────────────────────────────────────────────────────────────────────
  ✓ Fichiers stagés
  ✓ Validations EF Core passées (si applicable)
  ✓ Commit créé localement
  ✓ Push vers origin/{branch} (si auto-push activé)

═══════════════════════════════════════════════════════════════════════════════
                         PROCHAINES ÉTAPES
═══════════════════════════════════════════════════════════════════════════════

1. Continuer à développer et committer:
   /gitflow:3-commit

2. Quand prêt, créer une Pull Request:
   /gitflow:7-pull-request {branch_name}

═══════════════════════════════════════════════════════════════════════════════
```

**Si des migrations EF Core sont incluses:**

```
═══════════════════════════════════════════════════════════════════════════════
                         COMMIT AVEC MIGRATIONS
═══════════════════════════════════════════════════════════════════════════════

COMMIT DETAILS
───────────────────────────────────────────────────────────────────────────────
  • Branche:   {branch_name}
  • Hash:      {commit_hash_short}
  • Message:   {commit_message}
  • Fichiers:  {N} fichiers modifiés

MIGRATIONS EF CORE INCLUSES
───────────────────────────────────────────────────────────────────────────────
  ✓ {timestamp}_{MigrationName}.cs
  ✓ {timestamp}_{MigrationName}.Designer.cs
  ✓ {Context}ModelSnapshot.cs (updated)

VALIDATIONS
───────────────────────────────────────────────────────────────────────────────
  ✓ Les 3 fichiers de migration sont présents
  ✓ Build vérifié
  ✓ Pas d'opérations destructives détectées

WORKFLOW STATUT
───────────────────────────────────────────────────────────────────────────────
  ✓ Fichiers stagés
  ✓ Validations EF Core passées
  ✓ Commit créé localement
  ✓ Push vers origin/{branch}

═══════════════════════════════════════════════════════════════════════════════
                         PROCHAINES ÉTAPES
═══════════════════════════════════════════════════════════════════════════════

1. Appliquer la migration en local:
   /efcore:db-deploy

2. Continuer à développer ou créer une PR:
   /gitflow:7-pull-request {branch_name}

═══════════════════════════════════════════════════════════════════════════════
```

---

## Modes

| Command | Action |
|---------|--------|
| `/gitflow:3-commit {msg}` | Commit with message |
| `/gitflow:3-commit` | Auto generate message |
| `/gitflow:3-commit --validate` | Validate without commit |
| `/gitflow:3-commit --dry-run` | Simulation |
