2

How can I delete all remote branches without a local tracking branch?

I have about 30 remote branches without local branches (that were deleted) and 20 local branches that track to a remote.

I kind find several posts on how to do the opposite.

EDIT: Looking for a one-liner to solve this so that I don't manually have to delete these branches one-by-one.

Bradford
  • 4,143
  • 2
  • 34
  • 44
  • Possible duplicate of [How to delete a Git branch both locally and remotely?](http://stackoverflow.com/questions/2003505/how-to-delete-a-git-branch-both-locally-and-remotely) – Makoto Oct 03 '16 at 19:57
  • While the duplicate talks about local deletions, it also very clearly talks about remote deletions as well. – Makoto Oct 03 '16 at 19:57
  • @Makoto yes, it deals with remotes, but only discusses when you want to delete both at once. My locals were already deleted. – Bradford Oct 03 '16 at 19:58
  • You don't have to delete both at once; you can delete the remote before you delete your local, or delete the local before you delete the remote. The order doesn't matter. Any other answer that would appear here would be echoing what's already stated in the other question. – Makoto Oct 03 '16 at 19:59
  • @Makoto The point is that there are 30 remote branches to delete and I don't want to do them one-by-one and was looking for a one-liner. Please reopen if one can't be provided – Bradford Oct 03 '16 at 20:01
  • `git push` takes multiple branch names, so `git push --delete origin ... ` will do the trick (using `--delete` to avoid having to prefix each individually with a colon). – torek Oct 03 '16 at 20:03
  • @torek thanks. how can I list all remote branches without a local branch? – Bradford Oct 03 '16 at 20:05
  • That's substantially harder. `git branch -r` lists all remote-tracking branches. If you have multiple remotes you get all branches for *all* remotes. Meanwhile "without a local branch" is poorly defined, because I can make local branch `zorg` track remote-tracking branch `origin/lilu`, and I can have local branch `korbindallas` that's *not* related to `origin/korbindallas`. You're going to have to make your own definition of "without a local branch". – torek Oct 03 '16 at 20:11
  • @torek. Thanks. That's why I was having a difficult time and posted to StackOverflow. Can we re-open so that someone can post that this is not possible and I can accept the answer for other users? While at the same time giving others a chance to reply? EDIT: I guess this is open again – Bradford Oct 03 '16 at 20:13
  • Well, you can't do it as a one-liner, but once you define precisely what you mean by "with/without a local branch" (does it matter if local branch `domino` tracks `sugar/white` but not `pizza/cardboard`?), it *is* possible to write a script, using `git for-each-ref` to iterate through the remote-tracking branch names and determine (by your algorithm) which ones to keep and which to delete. – torek Oct 03 '16 at 20:18

1 Answers1

2
branch_not_delete=( "master" "develop")

for branch in `git for-each-ref refs/remotes/origin --format '%(refname:short)' | grep -v HEAD`;  do
    branch_name="$(gawk '{gsub("origin/", "");print}' <<< $branch)"
    local_exists="$(git rev-parse --verify $branch_name 2> /dev/null)"

    if [[ -z "${local_exists// }" ]]; then
      if ! [[ " ${branch_not_delete[*]} " == *" $branch_name "* ]]; then
        read -p "Would you like to delete $branch_name (yes/no) [no]: " yesno
        yesno=${yesno:-no}
        if [[ "$yesno" == "yes" ]]; then
          git push origin :$branch_name
        fi
      fi
    fi
done 

Modified from https://stackoverflow.com/a/38776671/5399371

Updated with @torek's nice suggestion.

Community
  • 1
  • 1
Bradford
  • 4,143
  • 2
  • 34
  • 44
  • 1
    Minor improvement: replace `git branch -a | grep remotes` with `git for-each-ref refs/remotes/origin --format '%(refname:short)'` (you'll still need to remove `origin/` from each name). – torek Oct 03 '16 at 20:42