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.

  • Accidentally deleted many hidden files with “git clean -fd” and now I cannot install Ruby
  • the git hooks post-update seems not working
  • Send string with whitespaces as git commit message using bash
  • .bashrc not executed when starting GitBash
  • Howto sync database with git and git hooks and howto debug if it doesn't work
  • git-filter-branch with --index-filter : strange bash error ( ! : event not found)
  • 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
      STORY-123-Short-Description
      STORY-456-Another-Description
      STORY-789-Blah-Blah
    * 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:
    git 1.7.4.1
    ubuntu 10.04
    GNU bash, version 4.1.5(1)-release
    GNU grep 2.5.4

  • All lines removed from file and all lines added to file in commit
  • Jenkins Windows slave: Authentication failed if running as service
  • Translate authorized curl -u post request with JSON data to RestTemplate equivalent
  • gitignore my windows username
  • git diff file against its last change
  • Switch current branch in git bare repository
  • 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
      Story-123-a
      Story-123-b
      Story-123-c
    * 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
      branch
      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/)
    do
        git branch -d ${mergedBranch}
    done
    

    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/)
    do
        git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
    done
    

    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 ]
      then
        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' ]]
          then
            echo $branches_to_delete | xargs git branch -D
        fi
    else
      echo "This command takes one arg (match pattern) or no args (match all)"
    fi
    }
    

    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:
    
    dummy+test1
    dummy+test2
    dummy+test3
    
    Delete? [Y/n] 
    
    Git Baby is a git and github fan, let's start git clone.