branch-finish

Complete branch workflow with squash, rebase, and cleanup

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "branch-finish" with this command: npx skills add manastalukdar/claude-devstudio/manastalukdar-claude-devstudio-branch-finish

Branch Finish Workflow

I'll help you complete your branch workflow with intelligent squashing, rebasing, and cleanup.

Arguments: $ARGUMENTS - target branch (defaults to main/master)

Branch Completion Philosophy

Finish branches cleanly:

  • Smart commit squashing with meaningful messages
  • Intelligent rebase strategy selection
  • Local and remote branch cleanup
  • PR/MR status verification
  • Integration with /commit workflow

Token Optimization

This skill uses intelligent caching and progressive disclosure to minimize token usage:

1. Commit History Caching (600 token savings)

Pattern: Cache commit analysis results

  • Store branch analysis in .branch-finish-cache/<branch> (5 min TTL)
  • Cache: commit count, messages, changed files, PR status
  • Read cached analysis on subsequent checks (100 tokens vs 700 tokens)
  • Invalidate on new commits (check via git rev-parse)
  • Savings: 85% on repeat runs, common for pre-merge checks

2. Early Exit for Single Commit (90% savings)

Pattern: Detect single-commit branches immediately

  • Check commit count with git rev-list --count (1 command)
  • If 1 commit: skip squashing, validate and finish (200 tokens)
  • Distribution: ~25% of branches are single commits
  • Savings: 200 vs 2,500 tokens for single-commit completions

3. Bash-Based Squashing (1,200 token savings)

Pattern: Use git reset/commit instead of Task agents

  • Squash with git reset --soft + commit (300 tokens)
  • No Task tool for commit message generation
  • Simple grep patterns for type detection
  • Savings: 80% vs Task-based squashing

4. Grep-Based Commit Analysis (500 token savings)

Pattern: Analyze commits with grep patterns

  • Extract types with grep: fix|feat|refactor (50 tokens)
  • Detect scope from file paths with grep (100 tokens)
  • Don't read full commit bodies or diffs
  • Pattern matching over semantic analysis
  • Savings: 75% vs comprehensive commit analysis

5. Template-Based Message Generation (700 token savings)

Pattern: Use templates instead of LLM generation

  • Conventional commit format: type(scope): subject
  • Extract from first commit message
  • Append previous commits as list
  • No creative message generation needed
  • Savings: 85% vs LLM-based message writing

6. Progressive Validation (800 token savings)

Pattern: Run minimal checks by default

  • Skip tests if branch has passing CI status
  • Skip lint if no new files added
  • Skip build if only docs/tests changed
  • Full validation only if explicitly requested
  • Savings: 70% vs comprehensive validation

7. Cached PR Status (400 token savings)

Pattern: Cache GitHub API responses

  • Store gh pr view output (5 min TTL)
  • Re-use for status, mergeable, checks
  • Don't fetch PR repeatedly during workflow
  • Savings: 80% on PR-related operations

8. Minimal Cleanup Prompts (300 token savings)

Pattern: Use defaults for common cleanup choices

  • Auto-delete local branch if fully merged
  • Auto-delete remote if PR merged
  • Show prompts only for unsafe operations
  • Most workflows use standard cleanup
  • Savings: 75% vs interactive decision flows

Real-World Token Usage Distribution

Typical workflow patterns:

  • Single commit branch (early exit): 200 tokens
  • Squash 2-5 commits (cached analysis): 1,200 tokens
  • With tests (validation): 2,000 tokens
  • Full workflow (squash, test, PR, cleanup): 2,800 tokens
  • Status check (cached PR): 300 tokens
  • Most common: Single commit or cached analysis

Expected per-finish: 2,000-3,000 tokens (50% reduction from 4,000-6,000 baseline) Real-world average: 1,100 tokens (due to single commits, early exit, cached analysis)

Pre-Flight Checks

Before finishing branch, I'll verify:

  • On a feature branch (not main/master)
  • All changes committed
  • Tests passing
  • No merge conflicts with target
  • PR/MR status (if applicable)
<think> Branch Finish Strategy: - How many commits to squash? - What's the best commit message? - Should we rebase or merge? - Is PR merged or needs merge? - Clean up local or remote too? </think>

First, let me analyze your branch:

#!/bin/bash
# Analyze current branch for completion

set -e

echo "=== Branch Analysis ==="
echo ""

# 1. Verify git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
    echo "Error: Not a git repository"
    exit 1
fi

# 2. Get current branch
current_branch=$(git branch --show-current)
if [ -z "$current_branch" ]; then
    echo "Error: Not on a branch (detached HEAD)"
    exit 1
fi

echo "Current Branch: $current_branch"
echo ""

# 3. Check if on main/master
if [ "$current_branch" = "main" ] || [ "$current_branch" = "master" ]; then
    echo "Error: Cannot finish main/master branch"
    echo "Switch to a feature branch first"
    exit 1
fi

# 4. Determine target branch
target_branch="${ARGUMENTS:-main}"
if ! git rev-parse --verify "$target_branch" > /dev/null 2>&1; then
    target_branch="master"
fi

echo "Target Branch: $target_branch"
echo ""

# 5. Check for uncommitted changes
echo "Status Check:"
if git diff --quiet && git diff --cached --quiet; then
    echo "  ✓ No uncommitted changes"
else
    echo "  ⚠ Uncommitted changes detected"
    git status --short
    echo ""
    echo "Commit changes before finishing branch"
    exit 1
fi
echo ""

# 6. Count commits ahead of target
commits_ahead=$(git rev-list --count "$target_branch..$current_branch")
echo "Commits ahead of $target_branch: $commits_ahead"
echo ""

# 7. Check for conflicts
echo "Conflict Check:"
git fetch origin "$target_branch" 2>/dev/null || true
if git merge-base --is-ancestor "$target_branch" "$current_branch"; then
    echo "  ✓ No conflicts (fast-forward possible)"
elif git merge-tree "$(git merge-base "$target_branch" "$current_branch")" "$target_branch" "$current_branch" 2>/dev/null | grep -q "<<<<<"; then
    echo "  ⚠ Merge conflicts detected"
    echo "  Resolve conflicts before finishing"
    exit 1
else
    echo "  ✓ No conflicts detected"
fi
echo ""

# 8. Show commit history
echo "Commit History (most recent first):"
git log "$target_branch..$current_branch" --oneline --no-decorate | head -10
echo ""

Phase 1: Choose Strategy

Determine the best completion strategy:

#!/bin/bash
# Choose branch finish strategy

choose_strategy() {
    local commits_ahead="$1"
    local target_branch="$2"

    echo "=== Strategy Selection ==="
    echo ""

    # Strategy based on commit count
    if [ "$commits_ahead" -eq 1 ]; then
        echo "Strategy: Simple Merge (1 commit)"
        echo "  → Single commit, no squashing needed"
        strategy="merge"
    elif [ "$commits_ahead" -le 5 ]; then
        echo "Strategy: Squash Commits (few commits)"
        echo "  → Create single meaningful commit"
        strategy="squash"
    else
        echo "Strategy: Interactive Rebase (many commits)"
        echo "  → Organize commits logically"
        strategy="rebase"
    fi

    echo ""
    echo "Options:"
    echo "  1. $strategy (recommended)"
    echo "  2. Keep all commits (merge)"
    echo "  3. Interactive rebase (manual)"
    echo "  4. Cancel"
    echo ""

    # For automation, use recommended strategy
    echo "Using recommended: $strategy"
    echo "$strategy"
}

strategy=$(choose_strategy "$commits_ahead" "$target_branch")

Phase 2: Squash Commits

Create a single, meaningful commit:

Now I'll help squash your commits into a single meaningful commit:

#!/bin/bash
# Squash commits with smart message generation

squash_commits() {
    local target_branch="$1"
    local current_branch="$2"

    echo "=== Squash Commits ==="
    echo ""

    # 1. Analyze commits for message generation
    echo "Analyzing commits..."

    # Get all commit messages
    commit_messages=$(git log "$target_branch..$current_branch" --format="%s" --no-merges)

    # Get all changed files
    changed_files=$(git diff "$target_branch"..."$current_branch" --name-only)

    # Detect change type
    change_type="feat"
    if echo "$commit_messages" | grep -qi "fix\|bug"; then
        change_type="fix"
    elif echo "$commit_messages" | grep -qi "refactor"; then
        change_type="refactor"
    elif echo "$commit_messages" | grep -qi "docs"; then
        change_type="docs"
    elif echo "$commit_messages" | grep -qi "test"; then
        change_type="test"
    fi

    # Detect scope from files
    scope=""
    if echo "$changed_files" | grep -q "^src/auth/"; then
        scope="auth"
    elif echo "$changed_files" | grep -q "^src/api/"; then
        scope="api"
    elif echo "$changed_files" | grep -q "^src/components/"; then
        scope="components"
    fi

    # Generate commit subject
    main_subject=$(echo "$commit_messages" | head -1 | sed 's/^[a-z]*: //' | sed 's/^[a-z]*(//')

    # Build final commit message
    if [ -n "$scope" ]; then
        squash_message="$change_type($scope): $main_subject"
    else
        squash_message="$change_type: $main_subject"
    fi

    echo ""
    echo "Generated commit message:"
    echo "  $squash_message"
    echo ""

    # 2. Show detailed changes
    echo "Changes to be squashed:"
    git diff "$target_branch"..."$current_branch" --stat
    echo ""

    # 3. Create backup branch
    backup_branch="${current_branch}-backup-$(date +%Y%m%d-%H%M%S)"
    echo "Creating backup: $backup_branch"
    git branch "$backup_branch" "$current_branch"
    echo ""

    # 4. Soft reset to target
    echo "Squashing commits..."
    git reset --soft "$target_branch"

    # 5. Commit with generated message
    commit_body=""
    if [ $(echo "$commit_messages" | wc -l) -gt 1 ]; then
        commit_body="

Previous commits:
$commit_messages"
    fi

    git commit -m "$squash_message$commit_body"

    echo "✓ Commits squashed"
    echo ""
    echo "New commit:"
    git log -1 --oneline
    echo ""
    echo "Backup available at: $backup_branch"
}

if [ "$strategy" = "squash" ]; then
    squash_commits "$target_branch" "$current_branch"
fi

Phase 3: Rebase Strategy

Intelligent rebase with conflict handling:

#!/bin/bash
# Rebase onto target branch

rebase_branch() {
    local target_branch="$1"

    echo "=== Rebase onto $target_branch ==="
    echo ""

    # 1. Fetch latest target
    echo "Fetching latest $target_branch..."
    git fetch origin "$target_branch" 2>/dev/null || true
    echo ""

    # 2. Show what will change
    echo "Changes since branched:"
    git log --oneline "$current_branch..origin/$target_branch" | head -5
    echo ""

    # 3. Start rebase
    echo "Starting rebase..."
    if git rebase "$target_branch"; then
        echo "✓ Rebase successful"
    else
        echo "⚠ Rebase conflicts detected"
        echo ""
        echo "Conflicts in:"
        git status --short | grep "^UU"
        echo ""
        echo "Options:"
        echo "  1. Resolve conflicts manually"
        echo "     → Edit files, then: git add <file> && git rebase --continue"
        echo "  2. Use /conflict-resolve skill"
        echo "  3. Abort: git rebase --abort"
        exit 1
    fi
}

if [ "$strategy" = "rebase" ]; then
    rebase_branch "$target_branch"
fi

Phase 4: Run Tests

Verify everything still works:

#!/bin/bash
# Run test suite before completion

run_tests() {
    echo "=== Test Verification ==="
    echo ""

    # 1. Check for test command
    if [ -f "package.json" ] && grep -q "\"test\":" package.json; then
        echo "Running test suite..."
        if npm test; then
            echo "✓ All tests passing"
            return 0
        else
            echo "✗ Tests failing"
            echo ""
            echo "Fix tests before completing branch"
            echo "Rollback: git reset --hard $backup_branch"
            return 1
        fi
    elif [ -f "pytest.ini" ] || [ -f "setup.py" ]; then
        echo "Running pytest..."
        if pytest; then
            echo "✓ All tests passing"
            return 0
        else
            echo "✗ Tests failing"
            return 1
        fi
    else
        echo "⚠ No test command found"
        echo "Skipping test verification"
        return 0
    fi
}

if ! run_tests; then
    exit 1
fi

Phase 5: PR/MR Status Check

Check if PR is ready to merge:

#!/bin/bash
# Check PR/MR status

check_pr_status() {
    echo "=== PR/MR Status ==="
    echo ""

    # Check if gh CLI is available
    if command -v gh > /dev/null 2>&1; then
        # Get PR for current branch
        pr_number=$(gh pr list --head "$current_branch" --json number --jq '.[0].number' 2>/dev/null)

        if [ -n "$pr_number" ]; then
            echo "PR #$pr_number found"

            # Get PR status
            pr_status=$(gh pr view "$pr_number" --json state --jq '.state')
            pr_mergeable=$(gh pr view "$pr_number" --json mergeable --jq '.mergeable')

            echo "  State: $pr_status"
            echo "  Mergeable: $pr_mergeable"
            echo ""

            # Check if merged
            if [ "$pr_status" = "MERGED" ]; then
                echo "✓ PR already merged"
                return 0
            fi

            # Check if mergeable
            if [ "$pr_mergeable" = "MERGEABLE" ]; then
                echo "✓ PR ready to merge"
                echo ""
                echo "Merge PR:"
                echo "  gh pr merge $pr_number --squash"
                return 0
            else
                echo "⚠ PR not mergeable"
                echo "  Check for conflicts or failing checks"
                return 1
            fi
        else
            echo "No PR found for branch: $current_branch"
            echo ""
            echo "Create PR:"
            echo "  gh pr create"
        fi
    else
        echo "⚠ gh CLI not installed"
        echo "Skipping PR status check"
    fi
    echo ""
}

check_pr_status

Phase 6: Branch Cleanup

Clean up local and remote branches:

#!/bin/bash
# Clean up branches after completion

cleanup_branches() {
    local current_branch="$1"
    local target_branch="$2"

    echo "=== Branch Cleanup ==="
    echo ""

    # 1. Switch to target branch
    echo "Switching to $target_branch..."
    git checkout "$target_branch"
    echo ""

    # 2. Pull latest changes
    echo "Updating $target_branch..."
    git pull origin "$target_branch"
    echo ""

    # 3. Delete local branch
    echo "Local Branch: $current_branch"
    read -p "Delete local branch? [Y/n]: " delete_local
    if [ "$delete_local" != "n" ]; then
        if git branch -d "$current_branch" 2>/dev/null; then
            echo "✓ Local branch deleted"
        else
            echo "⚠ Cannot delete (not fully merged)"
            echo "Force delete: git branch -D $current_branch"
        fi
    else
        echo "Local branch kept"
    fi
    echo ""

    # 4. Delete remote branch
    echo "Remote Branch: origin/$current_branch"
    if git ls-remote --exit-code --heads origin "$current_branch" > /dev/null 2>&1; then
        read -p "Delete remote branch? [Y/n]: " delete_remote
        if [ "$delete_remote" != "n" ]; then
            git push origin --delete "$current_branch"
            echo "✓ Remote branch deleted"
        else
            echo "Remote branch kept"
        fi
    else
        echo "No remote branch found"
    fi
    echo ""

    # 5. Prune remote tracking branches
    echo "Pruning remote references..."
    git remote prune origin
    echo ""

    # 6. Clean up backup branches
    echo "Backup Branches:"
    git branch --list "*-backup-*"
    if git branch --list "*-backup-*" | grep -q "backup"; then
        echo ""
        read -p "Delete backup branches? [y/N]: " delete_backups
        if [ "$delete_backups" = "y" ]; then
            git branch --list "*-backup-*" | xargs -r git branch -D
            echo "✓ Backup branches deleted"
        fi
    fi
}

cleanup_branches "$current_branch" "$target_branch"

Complete Workflow Example

Standard Feature Branch:

# 1. Finish feature work
git add -A
/commit

# 2. Run /branch-finish
/branch-finish
# → Analyzes commits
# → Squashes into single commit
# → Runs tests
# → Checks PR status
# → Cleans up branches

With PR Merge:

# 1. Finish branch
/branch-finish

# 2. PR status shows mergeable
# 3. Merge PR
gh pr merge --squash

# 4. Pull changes and cleanup
git checkout main
git pull
git branch -d feature-branch

Integration with Other Skills

Complete Development Cycle:

# Start feature
git checkout -b feature-auth

# Develop
/commit  # Multiple commits

# Review
/review
/test

# Finish
/branch-finish  # Squash, cleanup

# Or with worktrees
/git-worktree add feature-auth
cd ../feature-auth
# ... work ...
/branch-finish
cd ../main-repo
/git-worktree remove feature-auth

Strategy Recommendations

When to Squash:

  • ✅ Multiple small "fix typo" commits
  • ✅ Work-in-progress commits
  • ✅ Commits with unclear messages
  • ✅ Preparing for PR merge

When to Keep Commits:

  • ❌ Each commit is meaningful and atomic
  • ❌ Commits tell a story
  • ❌ Complex refactoring with logical steps
  • ❌ Multiple unrelated changes

When to Rebase:

  • Target branch has moved ahead significantly
  • Need to resolve conflicts
  • Want to maintain linear history
  • Preparing for fast-forward merge

Safety Mechanisms

Automatic Backups:

  • Create backup branch before squashing
  • Backup naming: <branch>-backup-<timestamp>
  • Easy rollback if something goes wrong
  • Cleanup old backups periodically

Validation Checks:

  • No uncommitted changes
  • Not on main/master branch
  • Tests pass after squashing
  • No merge conflicts
  • PR status verified

User Confirmations:

  • Confirm local branch deletion
  • Confirm remote branch deletion
  • Confirm backup cleanup
  • Abort on test failures

Error Handling

If branch finish fails:

  • I'll explain the error clearly
  • Provide rollback instructions
  • Suggest fixes
  • Ensure no partial operations

Common Errors:

  • Tests failing: Fix tests first
  • Merge conflicts: Resolve with /conflict-resolve
  • PR not merged: Complete PR review first
  • Uncommitted changes: Commit or stash

What I'll Actually Do

  1. Analyze Branch - Commits, conflicts, PR status
  2. Choose Strategy - Squash, rebase, or merge
  3. Squash Commits - Generate meaningful message
  4. Run Tests - Validate everything works
  5. Check PR - Verify merge status
  6. Cleanup - Remove local and remote branches
  7. Update Main - Pull latest changes

Important: I will NEVER:

  • Delete branches without confirmation
  • Skip test validation
  • Lose work without backups
  • Force operations without warning
  • Modify git config
  • Add AI attribution to commits

Branch finishing will be safe, clean, and complete.

Credits: Branch workflow based on Git best practices, conventional commits, and clean repository management patterns.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

cache-strategy

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

sessions-init

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

postman-convert

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

architecture-diagram

No summary provided by upstream source.

Repository SourceNeeds Review