DEV Community

Olivier Buitelaar
Olivier Buitelaar

Posted on

Stop Ghosting Your Own Repos: Automate Stale Branch Cleanup with GitHub Actions

Stop Ghosting Your Own Repos: Automate Stale Branch Cleanup with GitHub Actions

You know the feeling. You run git branch -a and a wall of text scrolls past. Most of those branches are "temporary" fixes from 2024. Some are features that were merged months ago but never deleted. A few are experiments that died a quiet death.

Leaving stale branches lying around isn't just "messy." It slows down your team, makes it harder to find what's actually active, and creates a mental tax every time you look at your repository.

In this guide, I'll show you how to automate the audit and cleanup of stale branches using GitHub Actions, so you never have to manually "clean house" again.

The Problem with Manual Cleanup

Most developers treat branch cleanup like doing the dishes: they wait until the pile is so high they can't ignore it anymore. Then someone spends an hour guessing which branches are safe to delete, occasionally deleting something important by mistake, and inevitably missing half the mess.

The issues with manual cleanup are clear:

  1. It's inconsistent. It only happens when someone gets annoyed enough.
  2. It's risky. Without a clear record of when a branch was last touched, you're guessing.
  3. It's boring. No one wants to spend their Friday afternoon running git branch -D.

Automating the Audit

The first step in a safe cleanup process isn't deletion—it's visibility. You need to know which branches are stale before they disappear.

We can use a GitHub Action to scan the repository for branches that haven't seen a commit in a specific number of days (e.g., 90 days). Instead of deleting them immediately, the action should create a report.

Here is a basic implementation strategy using a custom GitHub Action I built called stale-branch-cleaner.

Step 1: Create the Cleanup Workflow

Create a file at .github/workflows/stale-branches.yml:

name: Stale Branch Audit
on:
  schedule:
    - cron: '0 9 * * 1'  # Run every Monday at 9:00 AM
  workflow_dispatch:      # Allow manual triggering

jobs:
  audit:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      issues: write
    steps:
      - name: Check for stale branches
        uses: ollieb89/stale-branch-cleaner@v1
        with:
          stale-days: '90'
          dry-run: 'true'      # Important: report only, don't delete yet
          create-issue: 'true'  # Create a GitHub Issue with the results
Enter fullscreen mode Exit fullscreen mode

Step 2: Review the Report

When this workflow runs, it won't touch your code. Instead, it will open a GitHub Issue that looks like this:

Title: 🧹 Stale Branch Report (2026-03-21)
Body:
The following branches have had no activity for over 90 days:

Branch Last Commit Author
feature/old-ui-experiment 2024-11-12 @dev-alpha
fix/temp-patch-v1 2025-01-05 @dev-beta
refactor/removed-module 2024-09-30 @dev-alpha

Total stale branches found: 3.

Moving to Auto-Deletion

Once you've run the audit for a few weeks and you're confident in the results, you can move to a "soft delete" or a full auto-cleanup.

The "Safe" Auto-Delete Pattern

I recommend a 90-day stale window with a "dry run" period of one month. This gives everyone on the team a chance to see the issue and "rescue" any branch they still care about (by simply pushing a dummy commit or re-labeling it).

To enable auto-deletion, update your workflow:

- name: Cleanup stale branches
  uses: ollieb89/stale-branch-cleaner@v1
  with:
    stale-days: '120'    # Older branches only
    dry-run: 'false'     # This will actually delete branches!
    create-issue: 'true' # Still create an issue to log what was removed
Enter fullscreen mode Exit fullscreen mode

Protecting Important Branches

Not all "inactive" branches are stale. You might have long-lived release branches, hotfix branches, or documentation branches that shouldn't be touched even if they haven't moved in 6 months.

The stale-branch-cleaner action automatically protects:

  • main
  • master
  • develop
  • Any branch matching release/*
  • Any branch matching hotfix/*

You can also provide a custom ignore list:

with:
  stale-days: '90'
  ignore-branches: 'archive/*,legacy-v1,important-refactor'
Enter fullscreen mode Exit fullscreen mode

Why This Matters for DevOps

Clean repositories lead to clean CI/CD.

  • Faster clones: Fewer refs to fetch when running shallow clones.
  • Clearer visibility: Your branch dropdown only shows work that is actually happening.
  • Lower security risk: Old branches often contain outdated dependencies with known vulnerabilities that might accidentally get merged or deployed.

Conclusion

Stop letting "temporary" branches become permanent fixtures of your repository. Automating the cleanup process turns a manual chore into a background process that keeps your development environment sharp and professional.

If you want to try this out, the tool is open source and available on GitHub:


Part of the GitHub Actions Toolkit

I'm building a suite of tools to make GitHub Actions more manageable for developers:

Give them a star if they help your workflow!

Top comments (0)