How to prune remote branches in Git

Remote branch pruning removes stale references to deleted remote branches, keeping local repository clean and preventing confusion from outdated branch listings. As the creator of CoreUI, a widely used open-source UI library, I’ve maintained clean Git repositories across distributed teams throughout my 25 years of development experience. The most effective approach is using git fetch –prune to automatically remove remote-tracking branches that no longer exist on remote. This method provides automatic cleanup during fetch operations, prevents accumulation of stale references, and maintains accurate branch listings without manual intervention.

Use git fetch –prune to remove stale remote-tracking branches, configure automatic pruning, clean up local branches tracking deleted remotes.

# View all remote-tracking branches
git branch -r

# Output shows:
#   origin/main
#   origin/feature-1
#   origin/feature-2
#   origin/old-feature  # This was deleted on remote but still shows locally

# Fetch and prune stale remote branches
git fetch --prune

# Output shows:
# From github.com:user/repo
#  x [deleted]         (none)     -> origin/old-feature
#  * [new branch]      new-feature -> origin/new-feature

# View updated remote branches
git branch -r

# Stale branches are now removed

Configure automatic pruning:

# Enable automatic pruning for all fetch operations
git config --global fetch.prune true

# Enable for specific remote only
git config remote.origin.prune true

# Verify configuration
git config --get fetch.prune
# Output: true

# Now regular fetch automatically prunes
git fetch

Prune specific remote:

# Prune only origin remote
git remote prune origin

# Dry run to see what would be pruned without actually pruning
git remote prune origin --dry-run

# Output shows:
# Pruning origin
# URL: [email protected]:user/repo.git
#  * [would prune] origin/deleted-branch-1
#  * [would prune] origin/deleted-branch-2

Clean up local branches tracking deleted remotes:

# List local branches and their tracking status
git branch -vv

# Output shows:
#   main           abc1234 [origin/main] Latest commit
#   feature-1      def5678 [origin/feature-1] Feature work
#   old-feature    ghi9012 [origin/old-feature: gone] Old work

# The "gone" indicates remote branch was deleted

# Delete local branches with gone remotes
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D

# Or use this safer version that prompts for each branch
git branch -vv | grep ': gone]' | awk '{print $1}' | while read branch; do
  echo "Delete local branch $branch? (y/n)"
  read answer
  if [ "$answer" = "y" ]; then
    git branch -D "$branch"
  fi
done

Comprehensive cleanup script:

#!/bin/bash
# cleanup-branches.sh

echo "Fetching latest changes and pruning stale remote branches..."
git fetch --prune --all

echo ""
echo "Remote branches:"
git branch -r

echo ""
echo "Local branches with deleted remotes:"
git branch -vv | grep ': gone]'

echo ""
echo "Do you want to delete local branches tracking deleted remotes? (y/n)"
read answer

if [ "$answer" = "y" ]; then
  git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D
  echo "Deleted local branches with gone remotes"
else
  echo "Skipped deletion"
fi

echo ""
echo "Remaining local branches:"
git branch

Prune with additional options:

# Prune and fetch all remotes
git fetch --prune --all

# Prune tags as well
git fetch --prune --prune-tags

# Verbose output showing what's being pruned
git fetch --prune --verbose

# Force prune even if up to date
git fetch --prune --force

Advanced pruning scenarios:

# View which remote branches would be pruned
git ls-remote --heads origin | awk '{print $2}' | sed 's|refs/heads/||' > /tmp/remote-branches.txt
git branch -r | grep 'origin/' | sed 's|origin/||' | while read branch; do
  if ! grep -q "^$branch$" /tmp/remote-branches.txt; then
    echo "Would prune: origin/$branch"
  fi
done

# Remove all remote-tracking branches for a remote
git branch -r | grep 'origin/' | sed 's|origin/||' | xargs -I {} git branch -r -d origin/{}

# Then fetch fresh references
git fetch origin

# Clean up reflog after pruning
git reflog expire --expire=now --all
git gc --prune=now --aggressive

Using Git aliases for common pruning tasks:

# Create helpful aliases
git config --global alias.prune-all '!git fetch --prune --all && git branch -vv | grep ": gone]" | awk "{print \$1}" | xargs -r git branch -D'

git config --global alias.cleanup '!git fetch --prune && git remote prune origin'

git config --global alias.branch-cleanup '!git branch --merged | grep -v "\*\|main\|master\|develop" | xargs -r git branch -d'

# Use aliases
git prune-all      # Fetch, prune, and delete local branches with gone remotes
git cleanup        # Basic fetch and prune
git branch-cleanup # Delete merged branches

Here the git fetch –prune removes remote-tracking branches that no longer exist on remote server. The –prune flag can be used with git fetch or as standalone git remote prune command. The fetch.prune configuration makes pruning automatic for all fetch operations. The git branch -vv shows local branches with tracking information including gone status for deleted remotes. The grep and awk pipeline filters branches with gone remotes for batch deletion. The –dry-run option previews pruning actions without making changes. The git reflog expire and git gc commands clean up dangling objects after pruning.

Best Practice Note:

This is the branch pruning workflow we use in CoreUI development to maintain clean repository state across our distributed team. Enable automatic pruning globally with fetch.prune config to prevent stale references from accumulating, communicate with team before deleting local branches to avoid losing work in progress, use –dry-run to preview pruning operations before executing them, and schedule regular repository maintenance including pruning, garbage collection, and reflog cleanup for optimal repository health.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to Clone an Object in JavaScript
How to Clone an Object in JavaScript

How to Open Link in a New Tab in HTML?
How to Open Link in a New Tab in HTML?

How to Use Bootstrap Dropdown in Angular – CoreUI Integration Guide
How to Use Bootstrap Dropdown in Angular – CoreUI Integration Guide

What is the Difference Between Null and Undefined in JavaScript
What is the Difference Between Null and Undefined in JavaScript

Answers by CoreUI Core Team