Many developers don't keep their local repositories clean. There is a way how to automate it though. Let's look at a few useful commands:
To clean refs to nonexistent branches in the remote:
$ git fetch --prune
--prune before fetching, remove any remote-tracking references that no longer exist on the remote.
To estimate how many branches merged into dev:
$ git branch --merged dev | wc -l
--merged option can filter list to branches that you have merged into the given branch. Squash and rebase merges usually aren't detected by
List of branches merged into dev:
$ git branch --merged dev
List of remote branches merged into dev:
$ git branch --merged dev --remote
If you are courageous then:
$ git branch --merged dev | egrep -v "(^\*|master|dev)" | xargs git branch -d
It removes all local branches that merged into dev (except dev and master).
This is a potentially damaging operation. It can delete branches actually needed.
So if you use the different approach to work with Git, you could remove some of branches manually instead. I hope you do not store all old branches, do you?