22

This is a common use-case for me, I clone a repository, checkout a branch, do some code changes, make multiple commits, then when it's stable, I do a push to remote, eventually the branch gets merged and deleted, and I'm left with a local branch with upstream gone.

I was looking for a safe way of deleting all such branches. From the description, it seemed like git remote prune origin is doing this exactly. But it doesn't seem to be working for me.

Seeing the following behaviour, the branch encrdb_init has been deleted from remote but the git remote prune origin command does not seem to prune it. I am not sure why.

$ git branch
  bugfix/encrdb_init
  * master
$
$ git remote prune origin
$
$ git checkout bugfix/encrdb_init
  Switched to branch 'bugfix/encrdb_init'
  Your branch is based on 'origin/bugfix/encrdb_init', but the upstream 
  is gone.
  (use "git branch --unset-upstream" to fixup)
$
$ git branch
  bugfix/encrdb_init <<< shouldn't this have been pruned?
  * master

for reference adding output of git remote show origin

$ git remote show origin
* remote origin
  Fetch URL: <redacted>
  Push  URL: <redacted>
  HEAD branch: master
  Remote branches:
    SSL_test                                                  tracked
    addNodeFix                                                tracked
    autoprefix                                                tracked
    release/1.0.2                                             tracked
  Local branches configured for 'git pull':
    bugfix/encrdb_init          merges with remote bugfix/encrdb_init
    master                      merges with remote master
    release/1.0.2               merges with remote release/1.0.2
  Local refs configured for 'git push':
    master                 pushes to master                 (up to 
date)
    release/1.0.2          pushes to release/1.0.2          (up to 
date)

$ git branch -vv
* bugfix/encrdb_init          341a078c [origin/bugfix/encrdb_init: gone] <redacted comment>`
jonnarosey
  • 520
  • 1
  • 8
  • 19
saketrp
  • 2,323
  • 3
  • 16
  • 18
  • 1
    Try `git remote prune origin --dry-run` to check the stale branches – Shubham Khatri Feb 16 '18 at 05:48
  • 1
    `git remote prune origin --dry-run` output is empty – saketrp Feb 16 '18 at 05:51
  • @ShubhamKhatri it returns empty because there is no more remote tracking branch to delete. And `bugfix/encrdb_init` is a *local* one (you can have a slash in a branch name) – VonC Feb 16 '18 at 05:54
  • you should receive a list of `your stale remote-tracking branches` with the above command. If you don't receive it, something else is probably wrong – Shubham Khatri Feb 16 '18 at 05:55
  • Possible duplicate of [What are the differences between git remote prune, git prune, git fetch --prune, etc](https://stackoverflow.com/questions/20106712/what-are-the-differences-between-git-remote-prune-git-prune-git-fetch-prune) – ckruczek Feb 16 '18 at 06:22
  • Thanks, it looks like the command only deletes the branches in `remote` but does not delete the local branch which is now left hanging. It looks like the command does not delete local branches, even the ones which have upstream gone. – saketrp Feb 16 '18 at 07:06
  • @saketrp yes, that is the all point of `git remote`: to update or delete in the *`remotes`* namespace. Not to tamper with local branches. – VonC Feb 16 '18 at 07:07
  • I have updated my answer with the actual commands that will delete the branches you want. – VonC Feb 16 '18 at 07:25

1 Answers1

17

The git remote prune command only deletes the remote tracking branches in the remotes/origin namespace.

Not the local branches.
The usual practice is to delete only merged local branches.

git branch (even with -vv) only shows local branches.
A branch can have a slash in its name

A remote tracking branch is in the remotes/origin namespace, and record what was fetch.
An upstream branch is a remote branch associated to a local branch in order for said local branch to know where to push.

git remote prune correctly remove the remote tracking branch, which happens to be the upstream branch for the local bugfix/encrdb_init branch.
That is why you see origin/bugfix/encrdb_init: gone: the remote tracking branch is gone.


The OP adds:

from the description, it seemed like git remote prune origin is doing this exactly. But it doesn't seem to be working for me.

No, the description does not mention local branches.

Deletes all stale remote-tracking branches under <name>.
These stale branches have already been removed from the remote repository referenced by <name>, but are still locally available in "remotes/<name>".

<name> here is the name of the remote repo referenced by git remote -v.
Usually "origin".
git remote prune will delete branches registered in remotes/origin (not the "remote(s)"). It will not delete local branches.

To "safely" delete local branches, you should:

That last option is flaky:

  • I prefer using git branch -d instead of -D, in order to delete only branches that are already merged.
  • you might end up deleting branches with a commit message contains the string ": gone"

A better way to list those branches is:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)"
Edwin Diaz
  • 1,693
  • 1
  • 12
  • 16
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • OP is trying `git remote prune origin` which should delete stale branches from the local, your answer doesn not answer the question – Shubham Khatri Feb 16 '18 at 05:43
  • Yes, the branch `bugfix/encrdb_init` has been merged to master and deleted at remote, but git does not delete it. – saketrp Feb 16 '18 at 05:45
  • @saketrp my answers stands: git remote prune won't delete a local branch. bugfix/encrdb_init is a local branch. – VonC Feb 16 '18 at 05:45
  • @ShubhamKhatri my answer stands. – VonC Feb 16 '18 at 05:46
  • Isn't it a tracking branch? as evident from the output of `git remote show origin` – saketrp Feb 16 '18 at 05:46
  • @saketrp no it is not. – VonC Feb 16 '18 at 05:47
  • @VonC How can I see this? Even the verbose command output shows this, doesn't it mean its a tracking branch? – saketrp Feb 16 '18 at 05:54
  • git branch alone gives you local branches only. It shows you a local branch and mentions its upstream branch is gone. – VonC Feb 16 '18 at 05:55
  • @saketrp I have to go to work, I will catch up later. In the meantime, my answer stands. – VonC Feb 16 '18 at 06:02
  • Sure, but isn't a local branch with upstream same as a tracking branch? and isn't this command supposed to delete such branches where upstream is gone? If not, what is the exact purpose of this command? – saketrp Feb 16 '18 at 06:11
  • @saketrp I just edited the answer to add links and references – VonC Feb 16 '18 at 07:07