102

At one point I thought that git fetch origin --prune deleted local branches that were no longer present on the server. Somehow this is not my experience at the moment.

I ran this command, and the local branch was not deleted. It is not currently checked out. I ran git branch -vv to check this info, and I see

feature/MyGreatFeature           f30efc7 [origin/feature/MyGreatFeature: gone]

So it seems to know that it is gone. Why would it not delete my local branch?

Running git version 2.7.4 (Apple Git-66)

3

7 Answers 7

104

The following command chain can be used to delete local branches:

git branch --v | grep "\[gone\]" | awk '{print $1}' | xargs git branch -D
  • git branch --v lists the local branches verbosely
  • grep "\[gone\]" finds all the branches whose remote branch is gone
  • awk '{print $1}' outputs only the name of the matching local branches
  • xargs git branch -D deletes all the matching local branches

This should work on MacOS as well as *nix environments.

4
  • 4
    this is a great solution, but now git defaults to using system language and [gone] might be a different string
    – Agos
    Commented Apr 30, 2020 at 16:44
  • This works perfect in MacOS and *nix. If someone is looking for similar functionality of windows, below commands will be useful: 1) git branch --v | find "[gone]" > tmpBranches.txt 2) for /f "tokens=1" %a in (tmpBranches.txt) do git branch -D %a 3) del tmpBranches.txt Commented Apr 27, 2021 at 19:21
  • After trying so many solutions on other threads this is what finally worked for me. Thanks a lot!
    – Harry
    Commented Dec 10, 2021 at 8:25
  • 1
    Nice. I turned this into a git alias: purge = !git branch --v | grep '\\[gone\\]' | awk '{print $1}' | xargs git branch -D
    – sitecorepm
    Commented Aug 9, 2023 at 18:15
82

The various prune options (git remote update --prune, git remote prune, git fetch --prune) only delete remote-tracking branches.1

You'll need to manually delete local branches you no longer want, or change or remove their upstream setting if the remote-tracking branch no longer exists. Note that each local branch can record a remote and/or branch that do not now, or even never did, exist. In this case Git mostly acts as if those local branches have no upstream set, except that since version 1.8.5, several commands report the upstream as "gone" or otherwise invalid, and may suggest using --unset-upstream.


1More precisely, they delete destination refs after doing the refspec mapping from the command line or fetch lines from the configuration. Hence, for fetch mirrors, they can delete local branches. Most clones are not set up as fetch mirrors, though.

There were some recent bug fixes for complex mappings, to make sure that Git did not prune a mapped branch in some cases when it should not. For any normal repository—ordinary clone or pure fetch mirror—these fixes have no effect; they matter only if you have complicated fetch configurations.

2
  • if there is a branch listed in the [] on git branch -vv isn't it a remote-tracking branch in that case?
    – yano
    Commented Jun 6, 2016 at 18:40
  • 1
    Not necessarily: the thing in [...] is simply the upstream. If the upstream is a remote-tracking branch, that's when it's likely to get pruned. In your example, you have [origin/feature/MyGreatFeature: gone] which looks like a remote-tracking branch that has already been pruned. Git still has local branch feature/MyGreatFeature, and in .git/config, that branch still has its remote set to origin and its upstream set. You can, e.g., delete the local branch (which deletes its tracking info), or --unset-upstream on it if you want to keep the local branch with no upstream set.
    – torek
    Commented Jun 6, 2016 at 19:09
21

This is how I do it with Powershell.

PS> git branch --v | ? { $_ -match "\[gone\]" } | % { -split $_ | select -First 1 } | % { git branch -D $_ }

You can then create an alias like:

PS> Function func_gitprune { git branch --v | ? { $_ -match "\[gone\]" } | % { -split $_ | select -First 1 } | % { git branch -D $_ } }

PS> Set-Alias -Name gitprune -Value func_gitprune

and execute it every time you need by running

PS> gitprune
2
  • Would this benefit from running a git fetch beforehand so you're in sync? something like & git fetch --prune; & git branch --v | ? { $_ -match "\[gone\]" } | % { -split $_ | select -First 1 } | % { git branch -D $_ }
    – sommmen
    Commented Sep 15, 2021 at 9:25
  • I came up with very similar: git branch --v | ? {$_.contains('[gone]')} | % {$_.trim().split()[0].trim()} | % {git branch -D $_}
    – Shanerk
    Commented Apr 13, 2023 at 14:51
9

The command you want is

$ git remote prune origin

This question is almost word for word what you're looking for.

4
  • For more git branching/merging madness, check this question out. Commented Jun 6, 2016 at 18:25
  • When you say "not working", what do you mean? It's failing with an error? Does the command succeed but it's not having the desired effect? Commented Jun 6, 2016 at 18:34
  • 7
    right it "succeeds" (there is no output) and nothing happens, the branches still have the "gone" tag
    – yano
    Commented Jun 6, 2016 at 18:39
  • 21
    @jonathan: git remote prune origin only deletes your remote-tracking branch (e.g. remotes/origin/mybranch). It does not delete your local branch (e.g. mybranch). You have to delete those separately.
    – wisbucky
    Commented Jan 25, 2018 at 21:51
3

For me this line works:

git branch -vv | grep "gone" | awk '{print $1}' | xargs git branch -D
6
  • 3
    this is exactly shown here stackoverflow.com/a/59228595/571778 but has less explanation
    – yano
    Commented Jul 20, 2020 at 23:08
  • 1
    There is a bit diffrent 1. -vv VS --v 2. grep "gone" VS grep "[gone]"
    – Eliya
    Commented Jul 21, 2020 at 8:14
  • 1
    what if you name your branch gone
    – yano
    Commented Jul 21, 2020 at 21:27
  • 2
    @yano then your branch will be gone
    – Kye W Shi
    Commented Jan 19, 2021 at 23:02
  • 1
    You appear to have not read the previous answers which covered this a long time before . stackoverflow.com/a/59228595/37370
    – RichieHH
    Commented Apr 5, 2021 at 23:11
1

In case you need the Windows Command Line version:

git fetch --all --prune
git branch --all --verbose | for /F "tokens=1" %i in ('findstr /c:"[gone]"') do git branch -D %i
2
  • The second command doesn't work for me in Windows. I get the error "[gone]"') was unexpected at this time.
    – SkyWalker
    Commented Mar 6, 2023 at 13:51
  • Maybe you can just remove the double quotes @SkyWalker Commented Mar 13, 2023 at 15:28
0

In case people need the PowerShell version:

git branch --v | Select-String -Pattern ".*\[gone\].*" | ForEach-Object{($_ -split "\s+")[1]} | ForEach-Object{git branch -D $_}

Not the answer you're looking for? Browse other questions tagged or ask your own question.