GitScrum / Docs
All Best Practices

Automating Branch Management | Git Workflow Automation

Automate branch naming validation, stale branch cleanup, and protection rules. Reduce manual Git overhead with pre-push hooks and CI integration.

6 min read

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

  • Enforce naming β€” Consistent, parseable patterns
  • Auto-delete merged β€” Clean repository
  • Protect main β€” Quality gates
  • Link to tasks β€” Full traceability
  • 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
    

    Related Solutions