Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@robmiller
Last active February 27, 2024 10:09
Show Gist options
  • Save robmiller/5133264 to your computer and use it in GitHub Desktop.
Save robmiller/5133264 to your computer and use it in GitHub Desktop.
A script for cleaning up Git repositories; it deletes branches that are fully merged into `origin/master`, prunes obsolete remote tracking branches, and as an added bonus will replicate these changes on the remote.
#!/bin/bash
# git-cleanup-repo
#
# Author: Rob Miller <rob@bigfish.co.uk>
# Adapted from the original by Yorick Sijsling
git checkout master &> /dev/null
# Make sure we're working with the most up-to-date version of master.
git fetch
# Prune obsolete remote tracking branches. These are branches that we
# once tracked, but have since been deleted on the remote.
git remote prune origin
# List all the branches that have been merged fully into master, and
# then delete them. We use the remote master here, just in case our
# local master is out of date.
git branch --merged origin/master | grep -v 'master$' | xargs git branch -d
# Now the same, but including remote branches.
MERGED_ON_REMOTE=`git branch -r --merged origin/master | sed 's/ *origin\///' | grep -v 'master$'`
if [ "$MERGED_ON_REMOTE" ]; then
echo "The following remote branches are fully merged and will be removed:"
echo $MERGED_ON_REMOTE
read -p "Continue (y/N)? "
if [ "$REPLY" == "y" ]; then
git branch -r --merged origin/master | sed 's/ *origin\///' \
| grep -v 'master$' | xargs -I% git push origin :% 2>&1 \
| grep --colour=never 'deleted'
echo "Done!"
fi
fi
@jschank
Copy link

jschank commented Sep 24, 2017

Here is a version of this function (a little more elaborate) written in fish shell, for those who use fish.

# git-clean-branches
#
# * Will delete all fully merged local branches
#   and any closed remote branches.
# * User is prompted to continue before deleting.
# * Pass in -d or --dry-run to see what would happen without changing anything
# 
# Credit to Rob Miller <rob@bigfish.co.uk>
# Adapted from the original by Yorick Sijsling
# See: https://gist.github.com/robmiller/5133264
# Author John Schank
# Errors are mine, use at your own risk.

function git-clean-branches --description="Delete all fully merged local and remote branches"
    for option in $argv
        switch "$option"
            case -d --dry-run
                set DRY_RUN true                
            case \*
                printf "Error: unknown option %s\n" $option
        end
    end

    #  Make sure we're on master first
    git checkout master > /dev/null ^&1

    # Make sure we're working with the most up-to-date version of master.
    git fetch

    # Prune obsolete remote tracking branches. These are branches that we
    # once tracked, but have since been deleted on the remote.
    git remote prune origin

    # List all the branches that have been merged fully into master, and
    # then delete them. We use the remote master here, just in case our
    # local master is out of date.
    set -l MERGED_LOCAL (git branch --merged origin/master | grep -v 'master$' | string trim)
    if test -n "$MERGED_LOCAL"
        echo
        echo "The following local branches are fully merged and will be removed:"
        echo $MERGED_LOCAL
        read --local --prompt-str "Continue (y/N)? " REPLY
        if test "$REPLY" = "y"
            for branch in $MERGED_LOCAL
                if test $DRY_RUN
                    echo "Would delete local branch: '$branch'"
                else
                    echo "Deleting local branch: '$branch'"
                    git branch --quiet --delete $branch 
                end
            end
        end        
    end

    # Now the same, but including remote branches.
    set -l MERGED_ON_REMOTE (git branch -r --merged origin/master | sed 's/ *origin\///' | grep -v 'master$')

    if test -n "$MERGED_ON_REMOTE"
        echo
        echo "The following remote branches are fully merged and will be removed:"
        echo $MERGED_ON_REMOTE
        read --local --prompt-str "Continue (y/N)? " REPLY
        if test "$REPLY" = "y"
            for branch in $MERGED_ON_REMOTE
                if test $DRY_RUN
                    echo "Would delete remote branch: '$branch'"
                else
                    echo "Deleting remote branch: '$branch'"
                    git push --quiet origin :$branch 
                end
            end
        end
    end

    echo "Done!"
end

@MacDoogle
Copy link

What is the best way to run the first chunk of code, just copy and paste into bash?

@robmiller
Copy link
Author

@MacDoogle

  1. Put the code in a file called git-cleanup-repo
  2. Put that file in your path (e.g. in /usr/local/bin)
  3. Make sure it's executable (chmod +x /usr/local/bin/git-cleanup-repo)
  4. In a repository, run git cleanup-repo and it will run this script

If you want to do that in one go, run this:

$ curl https://gist.githubusercontent.com/robmiller/5133264/raw/1ee11ff5bda524e0aa4074cac95ac98c5c48181a/git-cleanup-repo > /usr/local/bin/git-cleanup-repo && chmod +x /usr/local/bin/git-cleanup-repo

then:

$ cd path/to/your/project
$ git cleanup-repo

@MacDoogle
Copy link

MacDoogle commented Jul 14, 2021 via email

@MacDoogle
Copy link

Sorry still a little unclear. I am on Windows 10 if that helps and using Azure DevOps repos.
What file extension should I save this as, aka what type of file?
Since it does not ask me what repo I presume it works in whatever repo you execute it in?

@afarooki-point
Copy link

@MacDoogle this is a bash script (look at the first line of the script), you can add the .sh extension to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment