26

How can I list any local branches that appear (as per .git/config) to be tracking remote branches that no longer exist? Remote branches are on GitHub in this case but I suspect their location has no relevance.

For example:

  1. I have local branches, a, b, c and d.
  2. a is tracking origin/a and c is tracking origin/c.
  3. b and d are not tracking remote branches.
  4. origin/a has been been merged back into master and was deleted during a repository clean-up; I no longer need to keep local branch a.
  5. If local branch a is checked out to the working tree, running git fetch or git pull results in the error Your configuration specifies to merge with the ref 'a' from the remote, but no such ref was fetched.

How would I produce the list containing only a and any other local branches that appear to be tracking remote branches that no longer exist?

I would like to identify these so that I can delete obsolete local branches I no longer need.

The list should not include local branches b or d that are not tracking remote branches, and also not c that is tracking origin/c, which still exists.

Steve Crane
  • 4,340
  • 5
  • 40
  • 63
  • related: http://stackoverflow.com/questions/15661853/list-all-local-branches-without-a-remote – lyl0o0o Jun 10 '14 at 15:18
  • You need to check the `.git/config` file for what branches have upstreams configured, and which they are. Assuming that a local branch has an upstream with an identical name is going to get you into trouble. – twalberg Jun 10 '14 at 16:22
  • I've revised your question based on your update, please review it and roll it back if the revision is still incorrect with what you're asking – STW Jun 24 '14 at 22:14
  • @STW your revision doesn't really convey what I was asking. I will revise the question again. – Steve Crane Jun 25 '14 at 08:02
  • @SteveCrane cool, your edits look good. I'm pretty sure my revised answer below is what you need – STW Jun 25 '14 at 13:58
  • Is there a solution to this? None of the answers are marked as accepted and I'm curious as well. – Mike Dec 04 '15 at 20:24
  • I know it's an old post but the jthill solution gave me a result much easier to parse than git branch -vv which is broken as soon as your description contains "[]" characters ... – Bertrand Sep 14 '17 at 19:38
  • After some testing. I believe the answer by Anton Styagun is correct. – TTT Jul 31 '20 at 16:09

4 Answers4

18

If your local branches are tracking the remote branch you can filter the list of branches so show the ones that do not have a tracking branch with:

git branch -vv | grep -v origin

This will provide some extra information about the last commit that is on the branch but you can filter that out

git branch -vv | grep -v origin | awk '{print $1}'

This will only print the name of the branch that isn't tracking a remote branch.

Schleis
  • 41,516
  • 7
  • 68
  • 87
9
LANG=en git branch --format='%(if:equals=gone)%(upstream:track,nobracket)%(then)%(refname:short)%(end)' | grep '.'
Anton Styagun
  • 1,112
  • 14
  • 10
  • 1
    This is definitely the answer to OPs question, it should be accepted. – rossipedia Dec 17 '19 at 04:09
  • 1
    This seems to work very well when it is run after the `git remote prune origin` command, thank you! I used `xargs` to feed this into `git branch -D` to delete those branches as well. – Wade J Jan 07 '20 at 00:26
  • @tom_mai78101 I use it within a `git branch-purge` command. To make such a `git` command available create a `git-branch-puge` executable in your path like this: https://github.com/astyagun/.files/blob/268503c172f384279f11ac12a55634832cb54f72/bin/git-branch-purge. – Anton Styagun Apr 09 '20 at 16:09
  • @AntonStyagun Your github gist is missing. – tom_mai78101 Apr 10 '20 at 17:32
  • @tom_mai78101 I've made the repo public, try again – Anton Styagun Apr 10 '20 at 17:51
  • @AntonStyagun I thought this is something you add to the gitconfig alias or you add this to the .bashrc. Thanks though, I'm assuming you add this to the `/usr/local/bin` on Ubuntu. – tom_mai78101 Apr 10 '20 at 18:55
  • The answer is not fully cross platform (i.e. can't cut & paste the full answer and run in Powershell) but when isolated the `git branch` command in it does provide the answer to my question. Thank you. – Steve Crane Aug 02 '20 at 10:08
6

To list your local branches which track deleted remote branches you can use git remote prune --dry-run

For example (assuming your remote repository is named origin):

git fetch
git remote prune origin --dry-run

You can remove the --dry-run option to delete the branches from your local repository

STW
  • 44,917
  • 17
  • 105
  • 161
  • Reading up on this, it sounds like just what I needed but after trying it, I'm not sure it is. – Steve Crane Jun 25 '14 at 15:01
  • if your question has fundamentally changed, but this answers this particular question, then you can always ask another question ;) – STW Jun 25 '14 at 19:06
  • No, the question is the same. I ran out of time to clarify yesterday and will do so now. – Steve Crane Jun 26 '14 at 07:33
  • Reading up on this, it sounded like just what I needed but after trying it, I'm not sure it was. `git branch --list` results include `a`, then I ran `git remote prune origin` which said `* [pruned] origin/a`. Now `git branch --list` results still include `a`, `git checkout a` reported that the upstream was gone and suggested `git branch --unset-upstream`. I did that and can see in `.git/config` it is no longer tracking but the local branch remains and I must delete it myself. The result I hoped for was for the local branch to be deleted. This answer gets me part of the way there. – Steve Crane Jun 26 '14 at 07:39
  • I don't think this answer is correct. For example, when I run the command my output is empty, but I have many local branches that meet the question's criteria. – TTT Jul 31 '20 at 16:26
6
git for-each-ref refs/heads --format='%(refname:short) %(upstream)' \
| awk 'NF==1'

will do it. NF is awk's "number of fields", and its default action is print.

jthill
  • 55,082
  • 5
  • 77
  • 137