---
description: Phase 11 - Finish and finalize a GitFlow branch (tag + merge back)
agent: gitflow-finish
model: sonnet
---

# Phase 11: FINISH - Finaliser une branche GitFlow

Tu es expert GitFlow. Finalise une branche apres merge de la PR.

**Argument:** `$ARGUMENTS` = branche a finaliser (optionnel, **SCAN AUTOMATIQUE** si absent)

---

## Quand utiliser

| Situation | Action |
|-----------|--------|
| PR feature mergee | Cleanup uniquement |
| PR release mergee | Tag + merge back to develop |
| PR hotfix mergee | Tag + merge back to develop |

---

## ETAPE 1: SCAN PROACTIF (si pas d'argument)

> **COMPORTEMENT PROACTIF:** Si aucun argument fourni, scanner TOUTES les branches pour proposer celles qui sont pretes a finaliser.

### 1.1 Scanner toutes les branches GitFlow

```bash
git fetch --all --quiet

# Lister toutes les branches feature/release/hotfix
FEATURES=$(git branch -r | grep 'origin/feature/' | sed 's|origin/||' | tr -d ' ')
RELEASES=$(git branch -r | grep 'origin/release/' | sed 's|origin/||' | tr -d ' ')
HOTFIXES=$(git branch -r | grep 'origin/hotfix/' | sed 's|origin/||' | tr -d ' ')

ALL_BRANCHES="$FEATURES $RELEASES $HOTFIXES"
```

### 1.2 Verifier le statut PR de chaque branche

```bash
# Pour chaque branche, verifier:
for BRANCH in $ALL_BRANCHES; do
  # 1. PR mergee?
  PR_MERGED=$(gh pr list --head "$BRANCH" --state merged --json number,mergedAt --jq '.[0]')

  # 2. PR ouverte?
  PR_OPEN=$(gh pr list --head "$BRANCH" --state open --json number,url --jq '.[0]')

  # 3. Pas de PR?
  # Si pas de PR → suggerer /gitflow:7-pull-request

  # Categoriser
  if [ -n "$PR_MERGED" ]; then
    READY_TO_FINISH+=("$BRANCH")
  elif [ -n "$PR_OPEN" ]; then
    WAITING_FOR_MERGE+=("$BRANCH")
  else
    NEEDS_PR+=("$BRANCH")
  fi
done
```

### 1.3 Afficher le tableau de synthese

```
================================================================================
                    GITFLOW FINISH - SCAN DES BRANCHES
================================================================================

✅ PRETES A FINALISER (PR mergee):
┌─────────────────────────────┬───────────┬────────────┬─────────────────────┐
│ Branche                     │ Type      │ PR #       │ Mergee le           │
├─────────────────────────────┼───────────┼────────────┼─────────────────────┤
│ feature/add-user-auth       │ feature   │ #42        │ 2024-01-15 14:30    │
│ release/v1.5.0              │ release   │ #45        │ 2024-01-15 16:00    │
└─────────────────────────────┴───────────┴────────────┴─────────────────────┘

⏳ EN ATTENTE DE MERGE (PR ouverte):
┌─────────────────────────────┬───────────┬────────────┬─────────────────────┐
│ Branche                     │ Type      │ PR #       │ Statut              │
├─────────────────────────────┼───────────┼────────────┼─────────────────────┤
│ feature/add-orders          │ feature   │ #43        │ Review en cours     │
│ hotfix/fix-login            │ hotfix    │ #44        │ CI en cours         │
└─────────────────────────────┴───────────┴────────────┴─────────────────────┘

❌ SANS PR (action requise):
┌─────────────────────────────┬───────────┬────────────────────────────────────┐
│ Branche                     │ Type      │ Action suggeree                    │
├─────────────────────────────┼───────────┼────────────────────────────────────┤
│ feature/wip-refactor        │ feature   │ /gitflow:7-pull-request            │
│ feature/old-abandoned       │ feature   │ /gitflow:6-abort --branch          │
└─────────────────────────────┴───────────┴────────────────────────────────────┘

================================================================================
```

### 1.4 Proposition interactive

```javascript
// Si plusieurs branches pretes a finaliser
if (READY_TO_FINISH.length > 0) {
  AskUserQuestion({
    questions: [{
      question: "Quelle branche voulez-vous finaliser ?",
      header: "Finish",
      options: READY_TO_FINISH.map(branch => ({
        label: branch,
        description: `PR #${getPRNumber(branch)} mergee - ${getType(branch)}`
      })).concat([{
        label: "Toutes",
        description: "Finaliser toutes les branches pretes (dans l'ordre recommande)"
      }]),
      multiSelect: false
    }]
  })
} else if (WAITING_FOR_MERGE.length > 0) {
  // Afficher message d'aide
  console.log("Aucune branche prete a finaliser.")
  console.log("→ Attendez le merge des PRs en cours ou utilisez /gitflow:9-merge")
} else if (NEEDS_PR.length > 0) {
  // Afficher message d'aide
  console.log("Aucune branche prete. Creez d'abord une PR:")
  console.log("→ /gitflow:7-pull-request")
}
```

### 1.5 Ordre recommande pour "Toutes"

```
ORDRE DE FINALISATION RECOMMANDE:
  1. Hotfixes (urgents, vers main puis develop)
  2. Releases (vers main puis develop)
  3. Features (vers develop, par date de merge)
```

---

## ETAPE 2: Detecter le contexte (si argument fourni)

```bash
# Branche specifiee ou selectionnee
BRANCH=${ARGUMENTS:-$SELECTED_BRANCH}

# Determiner le type
if [[ $BRANCH == feature/* ]]; then TYPE="feature"
elif [[ $BRANCH == release/* ]]; then TYPE="release"
elif [[ $BRANCH == hotfix/* ]]; then TYPE="hotfix"
else
  echo "⚠️ '$BRANCH' n'est pas une branche GitFlow (feature/release/hotfix)"
  echo "→ Utilisez /gitflow:11-finish sans argument pour scanner les branches"
  exit 1
fi
```

## ETAPE 3: Verifier que PR est mergee

```bash
# Chercher PR associee
PR_INFO=$(gh pr list --head "$BRANCH" --state merged --json number,mergedAt,title --jq '.[0]')

# Si pas mergee
if [ -z "$PR_INFO" ]; then
  # Verifier si PR ouverte
  PR_OPEN=$(gh pr list --head "$BRANCH" --state open --json number,url --jq '.[0]')

  if [ -n "$PR_OPEN" ]; then
    PR_NUM=$(echo "$PR_OPEN" | jq -r '.number')
    echo "⚠️ PR #$PR_NUM existe mais n'est pas encore mergee"
    echo ""
    echo "Options:"
    echo "  1. Merger la PR:     /gitflow:9-merge $PR_NUM"
    echo "  2. Voir la PR:       gh pr view $PR_NUM --web"
    echo "  3. Abandonner:       /gitflow:6-abort --branch"
  else
    echo "⚠️ Aucune PR trouvee pour '$BRANCH'"
    echo ""
    echo "Options:"
    echo "  1. Creer une PR:     /gitflow:7-pull-request"
    echo "  2. Abandonner:       /gitflow:6-abort --branch"
  fi
  exit 1
fi
```

---

## Actions selon type

### Feature (simple cleanup)

```bash
# Detecter si on est dans un worktree et trouver le repo principal
CURRENT_DIR=$(pwd)
MAIN_WORKTREE=$(git worktree list --porcelain | grep -m1 "^worktree " | sed 's/worktree //')

# Revenir au repo principal AVANT de supprimer le worktree
cd "$MAIN_WORKTREE"

# Supprimer worktree si existe
WORKTREE_PATH="../worktrees/features/{name}"
if [ -d "$WORKTREE_PATH" ]; then
  git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || true
fi

# Supprimer branche locale
git checkout develop
git pull origin develop
git branch -d feature/{name}

# Supprimer branche remote (si pas fait par merge)
git push origin --delete feature/{name} 2>/dev/null || true
```

**Resume:**

```
═══════════════════════════════════════════════════════════════════════════════
                         FEATURE FINALISÉE
═══════════════════════════════════════════════════════════════════════════════

FINISH DETAILS
───────────────────────────────────────────────────────────────────────────────
  • Type:      feature
  • Branche:   feature/{name}
  • Mergée:    develop
  • PR:        #{number}

WORKFLOW STATUT
───────────────────────────────────────────────────────────────────────────────
  ✓ PR #{number} mergée avec succès
  ✓ Branche feature/{name} supprimée (local)
  ✓ Branche feature/{name} supprimée (remote)
  ✓ Worktree nettoyé

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

1. Créer une nouvelle feature:
   /gitflow:10-start feature {name}

2. Créer une release (si prêt pour production):
   /gitflow:10-start release

3. Voir le statut du repo:
   /gitflow:2-status

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

---

### Release (tag + merge back)

```bash
# 0. Detecter si on est dans un worktree et trouver le repo principal
CURRENT_DIR=$(pwd)
MAIN_WORKTREE=$(git worktree list --porcelain | grep -m1 "^worktree " | sed 's/worktree //')

# Revenir au repo principal AVANT toute operation
cd "$MAIN_WORKTREE"

# 1. Checkout main et pull
git checkout main
git pull origin main

# 2. Creer tag
VERSION=$(echo $BRANCH | sed 's/release\/v//')
git tag -a "v$VERSION" -m "Release v$VERSION"
git push origin "v$VERSION"

# 3. Merge back to develop
git checkout develop
git pull origin develop
git merge main --no-ff -m "chore: merge release v$VERSION back to develop"

# 4. AUTO-INCREMENT MINOR VERSION sur develop (prepare next release)
# Ceci evite que les futures features utilisent la meme version que la release
CURRENT_VERSION=$(cat package.json | jq -r '.version')

# Calculer la prochaine version MINOR (ex: 1.2.0 -> 1.3.0)
NEXT_VERSION=$(node -e "
  const [major, minor, patch] = '$CURRENT_VERSION'.split('.').map(Number);
  console.log([major, minor + 1, 0].join('.'));
")

# Mettre a jour package.json avec la nouvelle version
npm version $NEXT_VERSION --no-git-tag-version

# Committer le bump de version
git add package.json package-lock.json
git commit -m "chore: bump develop to v$NEXT_VERSION for next release"

git push origin develop

echo "OK Version develop incrementee: $CURRENT_VERSION -> $NEXT_VERSION"

# 5. Cleanup worktree + branche
WORKTREE_PATH="../worktrees/releases/v$VERSION"
if [ -d "$WORKTREE_PATH" ]; then
  git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || true
fi
git branch -d release/v$VERSION
git push origin --delete release/v$VERSION 2>/dev/null || true
```

**Resume:**

```
═══════════════════════════════════════════════════════════════════════════════
                         RELEASE FINALISÉE
═══════════════════════════════════════════════════════════════════════════════

RELEASE DETAILS
───────────────────────────────────────────────────────────────────────────────
  • Type:      release
  • Branche:   release/v{version}
  • Version:   v{version}
  • Tag:       v{version} ✓

VERSIONING
───────────────────────────────────────────────────────────────────────────────
  • Release:   v{version} → Déployée sur main
  • Develop:   {version} → {NEXT_VERSION} (auto-incrémenté)

WORKFLOW STATUT
───────────────────────────────────────────────────────────────────────────────
  ✓ PR mergée sur main
  ✓ Tag v{version} créé et poussé
  ✓ Main mis à jour
  ✓ Merge back vers develop effectué
  ✓ Version develop incrémentée ({version} → {NEXT_VERSION})
  ✓ Branche release/{version} supprimée
  ✓ Worktree nettoyé

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

✅ Release v{version} déployée avec succès!

1. Créer une nouvelle feature:
   /gitflow:10-start feature {name}

2. Créer un hotfix (si besoin):
   /gitflow:10-start hotfix {name}

3. Voir le statut du repo:
   /gitflow:2-status

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

---

### Hotfix (auto-increment PATCH + tag + merge back)

```bash
# 0. Detecter si on est dans un worktree et trouver le repo principal
CURRENT_DIR=$(pwd)
MAIN_WORKTREE=$(git worktree list --porcelain | grep -m1 "^worktree " | sed 's/worktree //')

# Revenir au repo principal AVANT toute operation
cd "$MAIN_WORKTREE"

# 1. Checkout main et pull
git checkout main
git pull origin main

# 2. AUTO-INCREMENT PATCH VERSION
# Lire la version actuelle
CURRENT_VERSION=$(cat package.json | jq -r '.version')

# Calculer la nouvelle version (PATCH increment)
# Ex: 1.7.1 → 1.7.2
NEW_VERSION=$(node -e "
  const [major, minor, patch] = '$CURRENT_VERSION'.split('.').map(Number);
  console.log([major, minor, patch + 1].join('.'));
")

# Mettre a jour package.json avec la nouvelle version
npm version $NEW_VERSION --no-git-tag-version

# Committer le bump de version
git add package.json package-lock.json
git commit -m "chore: bump version to $NEW_VERSION"

# 3. Creer tag avec la nouvelle version
git tag -a "v$NEW_VERSION" -m "Hotfix v$NEW_VERSION"
git push origin main
git push origin "v$NEW_VERSION"

# 4. Merge back to develop
git checkout develop
git pull origin develop
git merge main --no-ff -m "chore: merge hotfix v$NEW_VERSION back to develop"
git push origin develop

# 6. Cleanup worktree + branche
WORKTREE_PATH="../worktrees/hotfixes/{name}"
if [ -d "$WORKTREE_PATH" ]; then
  git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || true
fi
git branch -d hotfix/{name}
git push origin --delete hotfix/{name} 2>/dev/null || true
```

**⚠️ IMPORTANT:** Le bump de version PATCH est automatique. Pas besoin de le faire manuellement avant le finish.

**Resume:**

```
═══════════════════════════════════════════════════════════════════════════════
                         HOTFIX FINALISÉ
═══════════════════════════════════════════════════════════════════════════════

HOTFIX DETAILS
───────────────────────────────────────────────────────────────────────────────
  • Type:      hotfix
  • Branche:   hotfix/{name}
  • Correction: {description}

VERSIONING
───────────────────────────────────────────────────────────────────────────────
  • Avant:     v{CURRENT_VERSION}
  • Après:     v{NEW_VERSION} (PATCH auto-incrémenté)
  • Tag:       v{NEW_VERSION} ✓

WORKFLOW STATUT
───────────────────────────────────────────────────────────────────────────────
  ✓ Version incrémentée (PATCH): {CURRENT_VERSION} → {NEW_VERSION}
  ✓ package.json mis à jour
  ✓ Tag v{NEW_VERSION} créé et poussé
  ✓ Main mis à jour
  ✓ Merge back vers develop effectué
  ✓ Branche hotfix/{name} supprimée
  ✓ Worktree nettoyé

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

✅ Hotfix v{NEW_VERSION} déployé avec succès!

1. Créer une nouvelle feature:
   /gitflow:10-start feature {name}

2. Créer une release:
   /gitflow:10-start release

3. Voir le statut du repo:
   /gitflow:2-status

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

---

## Gestion des conflits (merge back)

Si conflit lors du merge back to develop :

```
⚠️ CONFLIT DETECTE - MERGE BACK
────────────────────────────────
Le merge de main vers develop a des conflits.

Fichiers en conflit:
{liste fichiers}

Options:
1. Resoudre manuellement puis: git merge --continue
2. Annuler: git merge --abort

Commande recommandee:
  Resoudre conflits dans IDE
  git add .
  git merge --continue
  git push origin develop
────────────────────────────────
```

---

## Cleanup automatique des worktrees

Apres chaque finish, un cleanup cible est effectue pour le worktree de la branche finalisee:

```bash
# Fonction de cleanup cible (appelee automatiquement)
cleanup_worktree_for_branch() {
  BRANCH=$1
  WORKTREE_BASE="../worktrees"

  # Determiner le chemin selon le type
  if [[ $BRANCH == feature/* ]]; then
    NAME=${BRANCH#feature/}
    WORKTREE_PATH="$WORKTREE_BASE/features/$NAME"
  elif [[ $BRANCH == release/* ]]; then
    VERSION=${BRANCH#release/}
    WORKTREE_PATH="$WORKTREE_BASE/releases/$VERSION"
  elif [[ $BRANCH == hotfix/* ]]; then
    NAME=${BRANCH#hotfix/}
    WORKTREE_PATH="$WORKTREE_BASE/hotfixes/$NAME"
  fi

  # Supprimer si existe
  if [ -d "$WORKTREE_PATH" ]; then
    git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || true
    rm -rf "$WORKTREE_PATH" 2>/dev/null || true
    git worktree prune
    echo "✓ Worktree nettoye: $WORKTREE_PATH"
  fi
}

# Appel automatique
cleanup_worktree_for_branch "$BRANCH"
```

**Note:** Pour un audit complet de tous les worktrees, utilisez:

```
/gitflow:12-cleanup
```

---

## Modes

| Commande | Action |
|----------|--------|
| `/gitflow:11-finish` | Finaliser branche courante |
| `/gitflow:11-finish feature/xxx` | Finaliser branche specifiee |
| `/gitflow:11-finish --dry-run` | Simulation |
| `/gitflow:11-finish --skip-tag` | Sans creation de tag |
