sensorario
sensorario

Reputation: 21620

Can I delete all the local branches except the current one?

I want to delete all branches that get listed in the output of ...

$ git branch

... but keeping current branch, in one step. Is that possible? If so, how?

Upvotes: 176

Views: 109853

Answers (20)

Lucas Kuhn
Lucas Kuhn

Reputation: 402

Working on macOS, remove the second grep if you also want to delete main

git branch | grep -v '*' | grep -v 'main' | xargs git branch -D
  • git branch -> list branches
  • grep -v '*' -> remove current one
  • grep -v 'main' -> remove main
  • xargs git branch -D -> pipe the result to git branch -D

Upvotes: 1

Robert Corvus
Robert Corvus

Reputation: 2126

For Windows, in Powershell use:

git branch | %{ $_.Trim() } | ?{ $_ -ne 'master' } | %{ git branch -D $_ }

If you get an error with above, this works for me now:

git branch -D  @(git branch | select-string -NotMatch "master" | Foreach {$_.Line.Trim()})

Upvotes: 24

KhogaEslam
KhogaEslam

Reputation: 3056

first (switch to the branch you want to keep > ex: master):

git checkout master

second (make sure you are on master):

git branch -D $(git branch)

And, If you're using PowerShell, use:

git branch -D $(git branch).Trim()

Upvotes: 179

User12547645
User12547645

Reputation: 8447

The current branch is marked with a * e.g

git branch 
  branchA
  branchB
* mybranch
  otherthing

Just do

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

Do delete all branches NOT marked with a *

Upvotes: 4

Ahmad Ismail
Ahmad Ismail

Reputation: 13862

In Linux, the command you are looking for is:

git branch --list | grep -v "^* $(git branch --show-current)$" | xargs git branch -D 

Here, git branch --show-current is used to get the current branch instead of hard coding a branch name.

Upvotes: 2

VirtualVAT
VirtualVAT

Reputation: 71

You can just keep checked out branch you need to keep - checkout master in the current git worktree then use:

git branch | xargs git branch -D

You'll see couple of errors about impossibility to remove the checked out branch and "*" branch (the symbol which is placed in the branches list before checked out branch). If you have multiple worktrees for the local git repository other branches which are checked out there will be also kept with the same error (and additional errors while removing "+" branch accordingly to the symbol shown in the branches list before branches which are checked out in other worktrees of the current repository.

Upvotes: 1

basecamp
basecamp

Reputation: 131

Assuming you seek to delete all except the master branch and the current feature branch(lets call it 'team/features/dev-branch-name'), I'd like to condense it down to say:

  1. First view the branches that you intend to delete
  2. Then delete them

To view the branches:

git branch | grep -v -Fx "$(git branch --show-current)\|master"

I see that some answers suggest grep -v "develop" | grep -v "master", but this is an AND condition i.e "give me all branch names that dont have "develop" in them and of those, find those that dont have "master" in them". Personally, I was looking for an OR condition.

Note to avoid accidental deletion of dev branch: although this looks great (due to no hardcoding of branch names), beware that you may not be checked out on the correct branch while you run this alongside a delete command. If your current branch checked out is master, then the above will list all except master only, whereas your intent was to list all except master and dev branch.

Thus I think it is best to make this foolproof by actually writing out the name of the branch you want to keep like so:

git branch | grep -v -Fx 'team/features/dev-branch-name\|master'

This has the benefit that you do not need to be checked out on a specific branch for it to correctly list.

Once you have successfully seen the branches you are about to delete, delete them by issuing:

git branch | grep -v -Fx 'team/features/dev-branch-name\|master' | xargs git branch -D

The above only adheres to deleting local branches. To delete remote branches too (which you'd want to do in cases like editing/trimming a cloned over repo for example), use:

git branch -r | grep -v -Fx 'team/features/dev-branch-name\|master' | cut -d'/' -f 2- |  xargs -L 1 git push origin --delete

Couple of things going on here: -r is to list all remote branches(if you've already deleted all the necessary local branches, then only the remote ones remain and you need to query for those specifically). -Fx gets all the exact matches and -v is a NOT condition. As per the man page for cut, to cut -d'/' -f 2- means to divvy up the result by '/' and then take field 2 until the end of the line (-f 2-). This is useful if you wish to pipe team/features/dev-branch-name instead of origin/team/features/dev-branch-name to xargs. If you don't cut -d'/' -f 2-, then you'd be saying git push origin --delete origin/branch instead of git push origin --delete branch. The former doesn't work. The -L 1 tell xargs to provide the left hand side input to the git push command one line at a time.

Even with the above, if you have remote branches that contain single quotation (') marks, it wont succeed on those. For that, you could try:

git branch -r | grep -v "'" | cut -d'/' -f 2- |  xargs -L 1 git push origin --delete

I did have to delete these funky single quotation riddled branches manually due to a fatal: invalid spec error.

Upvotes: 6

SagarG
SagarG

Reputation: 21

Easiest of all of the above:

  1. Get a list of all the branches by using - "git branch" command in your project folder
  2. Copy the list of branches which you get
  3. Remove "master" from the list and the ones which you want to keep
  4. Write commands to delete all branches together separated by "&&" (see example below)
  5. If you want to delete even those branches which have not been fully merged use "-D" instead of "-d" in below command. "-D" deletes branches forcefully

Example:

  • git branch -d branch1 && git branch -d branch2 && git branch -d branch3 && git branch -d branch4 && git branch -d branch5 && ...

This works for me and I find it super easy to remove many branches together and I also get a message for each branch which gets deleted and error messages for those branches which fail to get deleted.

Upvotes: 1

Justin Rice
Justin Rice

Reputation: 1301

I use this because I get to be more selective in what I do not want to delete. This below command removes every branch except master, develop and the current branch.

BRANCHES=$(git branch | egrep -v "(master|develop|\*)" | xargs git branch -D)
echo $BRANCHES

So I put this in my ~/.zshrc

delete_branches() {
  BRANCHES=$(git branch | egrep -v "(master|develop|\*)" | xargs git branch -D)
  echo $BRANCHES
}

alias cleanup_branches=delete_branches

Upvotes: 6

Dan Dye
Dan Dye

Reputation: 777

To delete all branches except for the current branch in one step:

git branch | grep -v $(git rev-parse --abbrev-ref HEAD) | xargs git branch -D

Upvotes: 21

NullifiedWarp
NullifiedWarp

Reputation: 41

So I see a lot of hard coded branch names here... And I think my answer here is more accurate to the "current branch" part of the question whilst keeping it single line and readable to bash newbies like me. Just to place credit where it's due, the answer is rather obviously also based on @pankijs's answer.

git branch | grep -v $(git branch --show-current) | xargs git branch -d

and I have it aliased on one line in my .bash_aliases in debian aswell.

alias gitbclean='git branch | grep -v $(git branch --show-current) | xargs git branch -d'

(Though I thinks some bash features need to be enabled for the sub command to run on some command lines)

Upvotes: 1

Aaron
Aaron

Reputation: 767

Assuming git branch shows the current branch prefixed with *; Using Powershell the following one liner will delete all branches that don't start with *.

git branch | ? { $_ -lt "*" } | % { git branch -D $_.Trim() }

? = Where-Object

% = Foreach-Object

Upvotes: 4

Asad Manzoor
Asad Manzoor

Reputation: 1465

Delete all merged branch locally:

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

Delete all branches except a specific branch:

git branch | grep -v "branch name" | xargs git branch -D

Delete all local branches except develop and master

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

Upvotes: 8

Asad Manzoor
Asad Manzoor

Reputation: 1465

Delete all branches except a specific branch:

git branch | grep -v "branch name" | xargs git branch -D

Delete all local branches except develop and master

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

Upvotes: 30

pankijs
pankijs

Reputation: 6903

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

will delete all branches except master (replace master with branch you want to keep, but then it will delete master)

Upvotes: 306

Vadorequest
Vadorequest

Reputation: 17997

Based on @pankijs answer, I made two git aliases:

[alias]
    # Delete all local branches but master and the current one, only if they are fully merged with master.
    br-delete-useless = "!f(){\
        git branch | grep -v "master" | grep -v ^* | xargs git branch -d;\
    }; f"
    # Delete all local branches but master and the current one.
    br-delete-useless-force = "!f(){\
        git branch | grep -v "master" | grep -v ^* | xargs git branch -D;\
    }; f"

To be added in ~/.gitconfig


And, as @torek pointed out:

Note that lowercase -d won't delete a "non fully merged" branch (see the documentation). Using -D will delete such branches, even if this causes commits to become "lost"; use this with great care, as this deletes the branch reflogs as well, so that the usual "recover from accidental deletion" stuff does not work either.

Basically, never use the -force version if you're not 300% sure you won't lose anything important. Because it's lost forever.

Upvotes: 87

Astrophage
Astrophage

Reputation: 1439

I once created this construct for my Windows environment. Maybe it'll help someone else. During execution, the master and current branch are not deleted. All other merged branches will be deleted regardless.

@echo off
cd PATH_TO_YOUR_REPO

REM -- Variable declerations
set "textFile=tempBranchInfo.txt"
set "branchToKeep=master"
set "branchToReplaceWith="
git branch --merged > %textFile%

REM -- remove "master" from list to keep the branch
for /f "delims=" %%i in ('type "%textFile%" ^& break ^> "%textFile%" ') do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    >>"%textFile%" echo(!line:%branchToKeep%=%branchToReplaceWith%!
    endlocal
)

REM -- execute branch delete commands
for /f "delims=" %%a in (%textFile%) do (
    git branch -D %%a
)

REM -- remove temp-file with branch information inside
DEL %textFile%

REM -- show local branches after the cleaning
echo Local branches:
git branch

pause 
exit

Upvotes: 3

elbik
elbik

Reputation: 1897

IMHO, the safest way of removing local branches is:

git branch -av | grep "\[gone\]" | awk '{print $1}' | xargs git branch -d

Also, more info related to this topic you can find Delete all local git branches

Upvotes: 0

Stepan Suvorov
Stepan Suvorov

Reputation: 26196

To remove all merged branches(except current -v ‘*’):

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

also I made such command for repo complete clean up:

alias git-clean="git branch  | grep -v '*' | grep -v 'master' | xargs git branch -D  && git reset --hard && git clean -d -x -f"

taken from here.

Upvotes: 14

torek
torek

Reputation: 488501

git branch -d (or -D) allows multiple branch names, but it's a bit tricky to automatically supply "all local branches excluding the one I'm on now" without writing at least a little bit of code.

The "best" (formally correct) method is to use git for-each-ref to get the branch names:

git for-each-ref --format '%(refname:short)' refs/heads

but then it's even harder to figure out which branch you're on (git symbolic-ref HEAD is the "formally correct" method for this, if you want to write a fancy script).

More conveniently, you can use git branch, which prints your local branch names preceded by two spaces or (for the current branch) by an asterisk *. So, run this through something to remove the * version and you're left with space-separated branch names, which you can then pass to git branch -d:

git branch -d $(git branch | grep -v '^*')

or:

git branch | grep -v '^*' | xargs git branch -d

Note that lowercase -d won't delete a "non fully merged" branch (see the documentation). Using -D will delete such branches, even if this causes commits to become "lost"; use this with great care, as this deletes the branch reflogs as well, so that the usual "recover from accidental deletion" stuff does not work either.

Upvotes: 13

Related Questions