Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git remote prune origin does not delete the local branch even if its upstream remote branch is deleted

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>`
like image 945
saketrp Avatar asked Feb 16 '18 05:02

saketrp


People also ask

Does git remote prune origin delete remote branches?

No git remote prune origin will only delete the refs to remote branches that no longer exist. Git stores both local and remote refs. A repository will have local/origin and remote/origin ref collections.

How do I delete a local branch if the remote branch is deleted?

First, use the git branch -a command to display all branches (both local and remote). Next, you can delete the local branch, using the git branch -d command, followed by the name of the branch you want to delete.

What does git remote prune origin does?

git remote prune origin This command deletes branch references to remote branches that do not exist. A remote branch can be deleted as a result of a delete-branch-after merge-operation.

Does git pull remove deleted branches?

This is because "git pull" does not remove remote tracking branches for branches deleted from remote repo.


1 Answers

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:

  • either considered the ones that are merged locally, for instance merged to master:

    git fetch -p && git branch -d $(git branch master --merged | grep master -v)
    
  • or, if you really want to delete immediately the one whose upstream branch is "gone":

    git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
    

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)"
like image 61
VonC Avatar answered Sep 21 '22 14:09

VonC