Try free
6 min read Guide 326 of 877

Automating Branch Management

Manual branch management is error-prone and time-consuming. Automated branch workflows ensure consistent naming, clean up stale branches, and enforce team standards. This guide covers practical automation strategies for branch management.

Branch Automation Types

AutomationBenefitEffort
Naming validationConsistencyLow
Auto-delete mergedClean repoLow
Stale cleanupReduced clutterMedium
Protection rulesQuality gatesLow
CI per branch typeRight testsMedium

Branch Naming

Enforcing Conventions

BRANCH NAMING AUTOMATION
════════════════════════

NAMING PATTERN:
─────────────────────────────────────
Standard format:
├── type/ticket-description
├── Examples:
│   ├── feature/AUTH-123-login-flow
│   ├── bugfix/BUG-456-null-pointer
│   ├── hotfix/PROD-789-payment-fix
│   └── chore/DEP-001-update-deps
└── Consistent, parseable

VALIDATION OPTIONS:
─────────────────────────────────────
1. Pre-commit hook:
   #!/bin/bash
   branch=$(git rev-parse --abbrev-ref HEAD)
   pattern="^(feature|bugfix|hotfix|chore)\/[A-Z]+-[0-9]+-"
   if [[ ! $branch =~ $pattern ]]; then
     echo "Invalid branch name: $branch"
     exit 1
   fi

2. CI check:
   - name: Validate branch name
     run: |
       if [[ ! "$GITHUB_HEAD_REF" =~ ^(feature|bugfix|hotfix)/ ]]; then
         echo "Invalid branch name"
         exit 1
       fi

3. Pre-receive hook (server-side):
   ├── Blocks invalid branches at push
   └── Strongest enforcement

LINK TO TASKS:
─────────────────────────────────────
Extract ticket from branch:
├── Parse branch name
├── Link PR to issue automatically
├── Update task status
├── Close task on merge
└── Full traceability

Auto-Cleanup

Managing Branch Lifecycle

BRANCH CLEANUP AUTOMATION
═════════════════════════

AUTO-DELETE ON MERGE:
─────────────────────────────────────
GitHub setting:
├── Settings → General
├── "Automatically delete head branches"
├── Enable ✓
├── Branch deleted when PR merged
├── No manual cleanup
└── Clean repository

GitLab:
├── Settings → Repository
├── "Enable auto-delete merged branches"
└── Same behavior

STALE BRANCH CLEANUP:
─────────────────────────────────────
Script to find stale branches:

# Find branches older than 30 days
for branch in $(git branch -r --merged | grep -v main); do
  last_commit=$(git log -1 --format=%ci "$branch")
  days_old=$(( ($(date +%s) - $(date -d "$last_commit" +%s)) / 86400 ))
  if [ $days_old -gt 30 ]; then
    echo "Stale: $branch ($days_old days)"
  fi
done

SCHEDULED CLEANUP:
─────────────────────────────────────
GitHub Action:
name: Branch Cleanup
on:
  schedule:
    - cron: '0 0 * * 0'  # Weekly
jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Delete stale branches
        run: |
          # Delete merged branches older than 14 days
          for branch in $(git branch -r --merged origin/main); do
            # Skip protected branches
            if [[ ! "$branch" =~ (main|develop|release) ]]; then
              git push origin --delete "${branch#origin/}"
            fi
          done

Branch Protection

Automated Quality Gates

BRANCH PROTECTION RULES
═══════════════════════

GITHUB PROTECTION SETTINGS:
─────────────────────────────────────
For main branch:
├── Require pull request before merging ✓
├── Require approvals: 1-2 ✓
├── Dismiss stale reviews ✓
├── Require status checks to pass ✓
│   ├── CI build
│   ├── Tests
│   └── Lint
├── Require branches to be up to date ✓
├── Require signed commits (optional)
├── Restrict pushes ✓
└── No force pushes ✓

RULESETS (NEWER):
─────────────────────────────────────
GitHub Rulesets:
├── Apply to multiple branches
├── Pattern matching (release/*)
├── Bypass permissions
├── More granular control
└── Organization-wide

BENEFITS:
─────────────────────────────────────
├── Consistent quality
├── No accidental pushes to main
├── Reviews enforced
├── Tests must pass
├── Team alignment
└── Automated enforcement

CI Per Branch Type

Conditional Workflows

CONDITIONAL CI PIPELINES
════════════════════════

BRANCH-BASED CI:
─────────────────────────────────────
Different pipelines per branch:

on:
  push:
    branches:
      - main
      - 'release/**'
      - 'feature/**'

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

  # Only on main
  deploy-staging:
    if: github.ref == 'refs/heads/main'
    needs: test
    runs-on: ubuntu-latest
    steps:
      - run: deploy-to-staging

  # Only on release branches
  deploy-production:
    if: startsWith(github.ref, 'refs/heads/release/')
    needs: test
    runs-on: ubuntu-latest
    steps:
      - run: deploy-to-prod

FEATURE BRANCH STRATEGY:
─────────────────────────────────────
Feature branches:
├── Run: lint, unit tests
├── Skip: integration tests, deploy
├── Fast feedback
└── Lower resource usage

Main branch:
├── Run: all tests
├── Run: security scan
├── Deploy: staging
└── Full validation

Release branches:
├── Run: all tests + smoke
├── Deploy: production
├── Tag release
└── Full production path

Notifications

Awareness Automation

BRANCH NOTIFICATIONS
════════════════════

LONG-LIVED BRANCH ALERTS:
─────────────────────────────────────
Alert when branch is too old:

- name: Check branch age
  run: |
    branch="${{ github.head_ref }}"
    created=$(gh pr view ${{ github.event.pull_request.number }} \
              --json createdAt -q '.createdAt')
    days_old=$(( ($(date +%s) - $(date -d "$created" +%s)) / 86400 ))
    
    if [ $days_old -gt 7 ]; then
      gh pr comment ${{ github.event.pull_request.number }} \
        --body "⚠️ This branch is $days_old days old. Consider merging or splitting."
    fi

MERGE CONFLICT DETECTION:
─────────────────────────────────────
Check for conflicts:
├── Automated check against main
├── Alert if conflicts detected
├── PR labels for conflict status
├── Slack notification
└── Early conflict resolution

BRANCH SYNC REMINDERS:
─────────────────────────────────────
├── Notify when behind main
├── Suggest rebase/merge
├── Prevent large drift
└── Keep branches current

GitScrum Integration

Branch-Task Connection

GITSCRUM BRANCH FEATURES
════════════════════════

AUTOMATIC LINKING:
─────────────────────────────────────
Branch naming includes task ID:
├── feature/GS-123-user-auth
├── GitScrum detects GS-123
├── PR linked to task
├── Activity visible on task
└── Full traceability

STATUS UPDATES:
─────────────────────────────────────
├── Branch created → Task "In Progress"
├── PR opened → Task "In Review"
├── PR merged → Task "Done"
├── Automatic status flow
└── No manual updates needed

VISIBILITY:
─────────────────────────────────────
On task card:
├── See active branches
├── See PR status
├── See merge status
├── Development context
└── Complete picture

Best Practices

For Branch Automation

  1. Enforce naming — Consistent, parseable patterns
  2. Auto-delete merged — Clean repository
  3. Protect main — Quality gates
  4. Link to tasks — Full traceability
  5. Conditional CI — Right tests for right branches

Anti-Patterns

BRANCH AUTOMATION MISTAKES:
✗ No branch protection on main
✗ Manual cleanup only
✗ Inconsistent naming
✗ Long-lived branches (weeks)
✗ Same CI for all branches
✗ No task linkage
✗ Branches never cleaned up
✗ Force push allowed on main