Delete all local git branches

I follow a development process where I create a new local branch for every new feature or story card. When finished I merge the branch into master and then push.

What tends to happen over time due to a combination of laziness or forgetfulness, is that I end up with a large list of local branches, some of which (such as spikes) may not have been merged.

  • .gitconfig not following bash alias for default editor command?
  • How to run bash script after git push
  • GitHub doesn't synchronize anymore
  • “git --bare init” does not produce just a .git directory
  • Upgrading Git Bash to run newly downloaded ruby 2.0.0
  • How print last commit info for every file in a git repository
  • I know how to list all my local branches and I know how to remove a single branch but I was wondering if there was a git command that allows me to delete all my local branches?

    Below is the output of the git branch --merged command.

    user@machine:~/projects/application[master]$ git branch --merged
    * master

    All attempts to delete branches listed with grep -v \* (as per the answers below) result in errors:

    error: branch 'STORY-123-Short-Description' not found.
    error: branch 'STORY-456-Another-Description' not found.
    error: branch 'STORY-789-Blah-Blah' not found.

    I’m using:
    ubuntu 10.04
    GNU bash, version 4.1.5(1)-release
    GNU grep 2.5.4

  • git is very very slow when tracking large binary files
  • Trying to delete remote branch; listed locally, repos says it doesn't exist
  • How to apply gitignore afterwards?
  • Xcode 4 restore file from earlier commit
  • Checking out remote git branch?
  • ssh-agent doesn't work / save me from typing passphrase for git
  • 11 Solutions collect form web for “Delete all local git branches”

    Just a note, I would upgrade to git 1.7.10. You may be getting answers here that won’t work on your version. My guess is that you would have to prefix the branch name with refs/heads/.

    CAUTION, proceed with the following only if you made a copy of your working folder and .git directory.

    I sometimes just go ahead and delete the branches I don’t want straight from .git/refs/heads. All these branches are text files that contain the 40 character sha-1 of the commit they point to. You will have extraneous information in your .git/config if you had specific tracking set up for any of them. You can delete those entries manually as well.

    The ‘git branch -d’ subcommand can delete more than one branch. So, simplifying @sblom’s answer but adding a critical xargs:

    git branch -D `git branch --merged | grep -v \* | xargs`

    or, further simplified to:

    git branch --merged | grep -v \* | xargs git branch -D 

    Importantly, as noted by @AndrewC, using git branch for scripting is discouraged. To avoid it use something like:

    git for-each-ref --format '%(refname:short)' refs/heads | grep -v master | xargs git branch -D

    Caution warranted on deletes!

    $ mkdir br
    $ cd br; git init
    Initialized empty Git repository in /Users/ebg/test/br/.git/
    $ touch README; git add README; git commit -m 'First commit'
    [master (root-commit) 1d738b5] First commit
     0 files changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 README
    $ git branch Story-123-a
    $ git branch Story-123-b
    $ git branch Story-123-c
    $ git branch --merged
    * master
    $ git branch --merged | grep -v \* | xargs
    Story-123-a Story-123-b Story-123-c
    $ git branch --merged | grep -v \* | xargs git branch -D
    Deleted branch Story-123-a (was 1d738b5).
    Deleted branch Story-123-b (was 1d738b5).
    Deleted branch Story-123-c (was 1d738b5).

    I found a nicer way in a comment on this issue on github:

    git branch --merged master --no-color | grep -v master | grep -v stable | xargs git branch -d

    edit: added no-color option and excluding of stable branch (add other branches as needed in your case)

    Parsing the output of git branch is not recommended, and not a good answer for future readers on Stack Overflow.

    1. git branch is what is known as a porcelain command. Porcelain commands are not designed to be machine parsed and the output may change between different versions of Git.
    2. There are user configuration options that change the output of git
      in a way that makes it difficult to parse (for instance, colorization). If a user has set color.branch then you will get control codes in the output, this will lead to error: branch 'foo' not found. if you attempt to pipe it into another command. You can bypass this with the --no-color flag to git branch, but who knows what other user configurations might break things.
    3. git branch may do other things that are annoying to parse, like
      put an asterisk next to the currently checked out branch

    The maintainer of git has this to say about scripting around git branch output

    To find out what the current branch is, casual/careless users may have
    scripted around git branch, which is wrong. We actively discourage
    against use of any Porcelain command, including git branch, in
    scripts, because the output from the command is subject to change to
    help human consumption use case.

    Answers that suggest manually editing files in the .git directory (like .git/refs/heads) are similarly problematic (refs may be in .git/packed-refs instead, or Git may change their internal layout in the future).

    Git provides the for-each-ref command to retrieve a list of branches.

    Git 2.7.X will introduce the --merged option to so you could do something like the below to find and delete all branches merged into HEAD

    for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
        git branch -d ${mergedBranch}

    Git 2.6.X and older, you will need to list all local branches and then test them individually to see if they have been merged (which will be significantly slower and slightly more complicated).

    for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
        git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}

    To delete every branch except the one that you currently have checked out:

    for b in `git branch --merged | grep -v \*`; do git branch -D $b; done

    I would recommend changing to git branch -D $b to an echo $b the first few times to make sure that it’ll delete the branches that you intend.

    I found it easier to just use text editor and shell.

    1. Type git checkout <TAB> in shell. Will show all local branches.
    2. Copy them to a text editor, remove those you need to keep.
    3. Replace line breaks with spaces. (In SublimeText it’s super easy.)
    4. Open shell, type git branch -D <PASTE THE BRANCHES NAMES HERE>.

    That’s it.

    The simpler way to delete all branches but keeping others like “develop” and “master” is the following:

    git branch | grep -v "develop" | grep -v "master" | xargs git branch -D

    very useful !

    I had a similar kind of situation and recently found the following command useful.

    git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep>/) printf "%s", $0 }'`

    If you want to keep multiple branches, then

    git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep1>|<Branch_You_Want_to_Keep2>/) printf "%s", $0 }'`

    hope this helps someone.

    If you don’t need to go through Git itself, you can also delete heads under .git/refs/heads manually or programmatically. The following should work with minimal tweaking under Bash:

    shopt -s extglob
    rm -rf .git/refs/heads/!(master)

    This will delete every local branch except your master branch. Since your upstream branches are stored under .git/refs/remotes, they will remain untouched.

    If you are not using Bash, or want to recurse a lot of Git repositories at once, you can do something similar with GNU find:

    find . \
        -path remotes -path logs -prune -o \
        -wholename \*.git/refs/heads/\* \! -name master -print0 |
    xargs -0 rm -rf

    The find solution is probably more portable, but pruning paths and filenames is tricky and potentially more error-prone.

    None of the answers satisfied my needs fully, so here we go:

    git branch --merged | grep -E "(feature|bugfix|hotfix)/" | xargs git branch -D && git remote prune origin

    This will delete all local branches which are merged and starting with feature/, bugfix/ or hotfix/. Afterwards the upstream remote origin is pruned (you may have to enter a password).

    Works on Git 1.9.5.

    The following script deletes branches. Use it and modify it at your own risk, etc. etc.

    Based on the other answers in this question, I ended up writing a quick bash script for myself. I called it “gitbd” (git branch -D) but if you use it, you can rename it to whatever you want.

    gitbd() {
    if [ $# -le 1 ]
        local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
        printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
        read -n 1 -r # Immediately continue after getting 1 keypress
        echo # Move to a new line
        if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
            echo $branches_to_delete | xargs git branch -D
      echo "This command takes one arg (match pattern) or no args (match all)"

    It will offer to delete any branches which match a pattern argument, if passed in, or all local branches when called with with no arguments. It will also give you a confirmation step, since, you know, we’re deleting things, so that’s nice.

    It’s kind of dumb – if there are no branches that match the pattern, it doesn’t realize it.

    An example output run:

    $ gitbd test
    Matching branches:
    Delete? [Y/n] 
    Git Baby is a git and github fan, let's start git clone.