Skip to content

Instantly share code, notes, and snippets.

@devinschumacher
Last active April 4, 2025 04:57
Show Gist options
  • Select an option

  • Save devinschumacher/4910e04aed206a50933784d56846e9b5 to your computer and use it in GitHub Desktop.

Select an option

Save devinschumacher/4910e04aed206a50933784d56846e9b5 to your computer and use it in GitHub Desktop.
How to Clean up Your Local Git Branches to Get In Sync With the Remote
title How to Clean up Your Local Git Branches to Get In Sync With the Remote
tags
git
git branch
git fetch
git fetch --prune
git branch -vv

How to Clean up Your Local Git Branches to Get In Sync With the Remote

  1. Check for branches not on the remote
  2. Remove references to branches no longer on the remote
  3. Delete all local branches that no longer exist on remote

git branch -vv

Check for branches that are not on the remote.

This will help you identify which branches still exist locally but have no corresponding branch on the remote.

Here's how you can interpret each part of the output from git branch -vv:

git branch -vv

Column 1: The first column lists the name of each local branch. The current branch is marked with an asterisk (*).

Example:

* dev
ds/37/site-build

Column 2: The second column shows the short version of the latest commit hash for each branch. This is the unique identifier of the latest commit on that branch.

Example:

3dfb897
de1beda

Column 3:

  1. [part in square brackets]
  2. appended by ahead/behind
  3. commit message

The part in square brackets [origin/branch-name] indicates the corresponding remote tracking branch. If a branch is being tracked by a local branch, you'll see the remote branch name here.

Example:

[origin/dev]
[origin/ds/37/site-build]

If a branch is ahead of or behind the remote, it will also show how many commits:

ahead 3: Your local branch is 3 commits ahead of the remote branch. These commits haven’t been pushed yet. behind X: The local branch is behind the remote by X commits, meaning you need to pull the latest changes.

Example:

[origin/ds/48/write-initial-tests-for-some-components: ahead 3]

Commit message: This is the message from the latest commit on that branch.

Breaking down specific lines:

* dev                                             3dfb897 [origin/dev] Merge pull request #56 from serpcompany/ds/53/fix-builds
  • You are currently on the dev branch (* dev).
  • The latest commit hash is 3dfb897.
  • This branch is tracking the remote branch origin/dev.
  • The latest commit was a merge pull request titled "Merge pull request #56 from serpcompany/ds/53/fix-builds".
  • The branch ds/48/testing-config is ahead of the remote branch origin/ds/48/write-initial-tests-for-some-components by 3 commits (meaning you have 3 commits locally that are not pushed).
ds/48/testing-config                            e7309d5 [origin/ds/48/write-initial-tests-for-some-components: ahead 3] run eslint after clearing cache
  • The latest commit hash is e7309d5, and the commit message is "run eslint after clearing cache."

What to do next:

  • For branches that are behind (if it says behind), you'll want to pull the latest changes.
  • For branches that are ahead, you might want to push your changes.
  • For branches with no upstream (missing [origin/...]), they have no remote branch. You could decide to either push them or delete them if they are no longer needed.

git fetch --prune

To clean up your local branches that no longer exist on the remote, you can follow these steps:

Fetch the latest updates: This will make sure your local repository is in sync with the remote.

git fetch --prune

The --prune option will automatically remove any references to branches that have been deleted from the remote.

image

Delete all local branches that no longer exist on remote

DRY RUN: This script will just print the branches you're about to delete:

# First, update your remote-tracking refs:
git fetch --prune

# Loop over all local branches
for branch in $(git branch --format="%(refname:short)"); do
  # Skip the current branch (and any other branches you want to keep, e.g., main, staging, or master)
  if [ "$branch" = "staging" ] || [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
    continue
  fi
  
  # Check if there is a remote branch with the same name
  if ! git show-ref --verify --quiet "refs/remotes/origin/$branch"; then
    echo "Would delete branch: $branch"
    # Uncomment the next line to actually delete the branch
    # git branch -D "$branch"
  fi
done

And if you're okay to delete them, run this one:

# First, update your remote-tracking refs:
git fetch --prune

# Loop over all local branches
for branch in $(git branch --format="%(refname:short)"); do
  # Skip the current branch (and any other branches you want to keep, e.g., main or staging)
  if [ "$branch" = "staging" ] || [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
    continue
  fi
  
  # Check if there is a remote branch with the same name
  if ! git show-ref --verify --quiet "refs/remotes/origin/$branch"; then
    echo "Deleting branch: $branch"
    git branch -D "$branch"
  fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment