---
name: step-finish
description: Finalize branch - tag, merge back, cleanup
next_step: null
---

# Step: FINISH - Finalize Branch

## YOUR TASK:

Create tags for releases/hotfixes, merge back to develop, clean up worktree and branch.

**ULTRA THINK about version tagging.**

---

## EXECUTION SEQUENCE:

### 1. Load Config and Determine Branch Context

```bash
# Load GitFlow config (sets GF_* variables)
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }

# Get current or specified branch
BRANCH=${1:-$(git rev-parse --abbrev-ref HEAD)}
BRANCH_TYPE=$(echo $BRANCH | cut -d'/' -f1)
BRANCH_NAME=$(echo $BRANCH | cut -d'/' -f2)

# Validate branch type
case "$BRANCH_TYPE" in
  feature|release|hotfix) ;;
  $GF_MAIN_BRANCH|$GF_DEVELOP_BRANCH)
    echo "❌ Cannot finish $GF_MAIN_BRANCH or $GF_DEVELOP_BRANCH branch"
    STOP
    ;;
  *)
    echo "❌ Unknown branch type: $BRANCH_TYPE"
    STOP
    ;;
esac
```

### 2. Verify Merge Status

```bash
git fetch origin

# Check if branch was merged
case "$BRANCH_TYPE" in
  feature)
    MERGED=$(git branch -r --merged origin/$GF_DEVELOP_BRANCH | grep "$BRANCH" | wc -l)
    TARGET="$GF_DEVELOP_BRANCH"
    ;;
  release|hotfix)
    MERGED=$(git branch -r --merged origin/$GF_MAIN_BRANCH | grep "$BRANCH" | wc -l)
    TARGET="$GF_MAIN_BRANCH"
    ;;
esac

[ "$MERGED" -eq 0 ] && {
  echo "⚠️ Branch $BRANCH not yet merged to $TARGET"
  echo "→ Run /gitflow merge first"

  if [ "$auto_mode" != true ]; then
    AskUserQuestion:
      header: "Continue"
      question: "Branch not merged. Continue anyway?"
      options:
        - label: "No, merge first"
        - label: "Yes, finish anyway"
  fi
}
```

### 3. Create Tag (Release/Hotfix only)

```bash
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
  # Get version from config (already loaded)
  VERSION="$GF_VERSION"

  # For hotfix, increment patch
  if [ "$BRANCH_TYPE" = "hotfix" ]; then
    MAJOR=$(echo $VERSION | cut -d'.' -f1)
    MINOR=$(echo $VERSION | cut -d'.' -f2)
    PATCH=$(echo $VERSION | cut -d'.' -f3)
    VERSION="$MAJOR.$MINOR.$((PATCH + 1))"
  fi

  TAG_NAME="v$VERSION"

  # Check if tag exists
  TAG_EXISTS=$(git tag -l "$TAG_NAME")
  [ -n "$TAG_EXISTS" ] && {
    echo "⚠️ Tag $TAG_NAME already exists"
    # Options: overwrite, different version, skip
  }

  # Create tag on main
  git checkout $GF_MAIN_BRANCH
  git pull origin $GF_MAIN_BRANCH
  git tag -a "$TAG_NAME" -m "$BRANCH_TYPE: $BRANCH_NAME"
  git push origin "$TAG_NAME"

  echo "✅ Created tag: $TAG_NAME"
fi
```

### 4. Merge Back to Develop (Release/Hotfix only)

```bash
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
  echo "Merging $TAG_NAME back to $GF_DEVELOP_BRANCH..."

  git checkout $GF_DEVELOP_BRANCH
  git pull origin $GF_DEVELOP_BRANCH

  # Merge with merge commit (preserve history)
  git merge $GF_MAIN_BRANCH -m "Merge $TAG_NAME back to $GF_DEVELOP_BRANCH"

  # Handle conflicts
  CONFLICTS=$(git diff --name-only --diff-filter=U | wc -l)
  [ "$CONFLICTS" -gt 0 ] && {
    echo "⚠️ Merge conflicts detected"
    git diff --name-only --diff-filter=U

    # Options: resolve, abort
  }

  git push origin $GF_DEVELOP_BRANCH

  # CRITICAL: Verify push and update tracking refs
  git fetch origin $GF_DEVELOP_BRANCH:refs/remotes/origin/$GF_DEVELOP_BRANCH --force --quiet
  LOCAL_SHA=$(git rev-parse HEAD)
  REMOTE_SHA=$(git rev-parse origin/$GF_DEVELOP_BRANCH)
  if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
    echo "✅ Push verified - local/remote in sync"
  else
    echo "⚠️ Push verification FAILED"
    echo "  Local:  $LOCAL_SHA"
    echo "  Remote: $REMOTE_SHA"
    echo "  → Try: git push origin $GF_DEVELOP_BRANCH --force-with-lease"
  fi

  echo "✅ Merged back to $GF_DEVELOP_BRANCH"
fi
```

### 5. Update Version (Release and Hotfix)

```bash
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
  MAJOR=$(echo $VERSION | cut -d'.' -f1)
  MINOR=$(echo $VERSION | cut -d'.' -f2)
  PATCH=$(echo $VERSION | cut -d'.' -f3)

  if [ "$BRANCH_TYPE" = "release" ]; then
    # Release: increment minor, reset patch
    NEXT_VERSION="$MAJOR.$((MINOR + 1)).0"
  else
    # Hotfix: increment patch (patch was already bumped for the tag, bump again for next dev)
    NEXT_VERSION="$MAJOR.$MINOR.$((PATCH + 2))"
  fi

  # Update config (using resolved config path)
  sed -i "s/\"current\": \".*\"/\"current\": \"$NEXT_VERSION\"/" "$GF_CONFIG_FILE"

  # Update source files
  # csproj, package.json, etc.

  git add -A
  git commit -m "chore: bump version to $NEXT_VERSION for development"
  git push origin $GF_DEVELOP_BRANCH

  # CRITICAL: Verify push and update tracking refs
  git fetch origin $GF_DEVELOP_BRANCH:refs/remotes/origin/$GF_DEVELOP_BRANCH --force --quiet
  LOCAL_SHA=$(git rev-parse HEAD)
  REMOTE_SHA=$(git rev-parse origin/$GF_DEVELOP_BRANCH)
  if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
    echo "✅ Push verified - local/remote in sync"
  else
    echo "⚠️ Push verification FAILED"
    echo "  Local:  $LOCAL_SHA"
    echo "  Remote: $REMOTE_SHA"
  fi

  echo "✅ Version bumped to $NEXT_VERSION"
fi
```

### 6. Clean Up Worktree

```bash
# Find worktree for this branch (use --porcelain for reliable parsing)
WORKTREE_PATH=$(git worktree list --porcelain | grep -B2 "branch refs/heads/$BRANCH" | grep "^worktree " | sed 's/^worktree //')

if [ -n "$WORKTREE_PATH" ] && [ -d "$WORKTREE_PATH" ]; then
  echo "Removing worktree: $WORKTREE_PATH"

  # Make sure we're not in the worktree directory
  cd "$GF_DEVELOP_PATH" 2>/dev/null || cd "$(git rev-parse --show-toplevel)"

  git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || {
    rm -rf "$WORKTREE_PATH"
  }

  git worktree prune
  echo "✅ Worktree removed"
fi
```

### 7. Delete Remote Branch

```bash
# Check if remote branch still exists
REMOTE_EXISTS=$(git branch -r --list "origin/$BRANCH")

if [ -n "$REMOTE_EXISTS" ]; then
  echo "Deleting remote branch: $BRANCH"
  git push origin --delete "$BRANCH" 2>/dev/null || {
    echo "⚠️ Could not delete remote branch (may already be deleted by PR)"
  }
fi

# Delete local branch
git branch -D "$BRANCH" 2>/dev/null || echo "Local branch already deleted"
```

### 8. Archive Plan (if exists)

```bash
PLAN_FILE=$(ls .claude/gitflow/plans/*${BRANCH_NAME}*.md 2>/dev/null | head -1)

if [ -f "$PLAN_FILE" ]; then
  ARCHIVE_NAME="${PLAN_FILE%.md}_DONE_$(date +%Y%m%d-%H%M%S).md"
  mv "$PLAN_FILE" "$ARCHIVE_NAME"
  echo "✅ Plan archived: $ARCHIVE_NAME"
fi
```

### 9. Summary

```
╔══════════════════════════════════════════════════════════════════╗
║                    BRANCH FINALIZED                               ║
╠══════════════════════════════════════════════════════════════════╣
║  Branch: {BRANCH}                                                 ║
║  Type:   {BRANCH_TYPE}                                            ║
╠══════════════════════════════════════════════════════════════════╣
║  Actions:                                                         ║
{if release or hotfix}
║  ✅ Tag created: {TAG_NAME}                                       ║
║  ✅ Merged back to develop                                        ║
{endif}
{if release}
║  ✅ Version bumped to {NEXT_VERSION}                              ║
{endif}
║  ✅ Worktree removed                                              ║
║  ✅ Branch deleted (local + remote)                               ║
╠══════════════════════════════════════════════════════════════════╣
║  Current branch: {main|develop}                                   ║
╠══════════════════════════════════════════════════════════════════╣
║  Ready for next: /gitflow start feature <name>                    ║
╚══════════════════════════════════════════════════════════════════╝
```

---

## ERROR HANDLING:

| Error | Solution |
|-------|----------|
| Branch not merged | Merge first or force finish |
| Tag exists | Overwrite or use different version |
| Merge back conflicts | Resolve manually |
| Worktree in use | Exit worktree first |

---

## SUCCESS CRITERIA:

- Tag created (for release/hotfix)
- Merged back to develop (for release/hotfix)
- Worktree removed
- Branch deleted
- Plan archived

## COMPLETION:

GitFlow cycle complete. Ready for next feature/release/hotfix.
