Is there any way to get the output of git branch -v
as a plumbing command? To be exact I'm only interested in the state of the branch, i.e. whether it is [gone]
or not.
For example given the following git branch -v
output:
> git branch -v
master 32c59ad4 Some other comment
someDeletedBranch 6aacba47 [gone] Some Comment
How could I get the someDeletedBranch
ref?
Note that this is not the same as git branch --merged
, if for example you're squashing pull requests into your master, so this solution won't do.
This is mostly in relation to this question, since this would be the missing part for being able to create a reliable script to remove local branches that don't exist on the remote any longer.
The plumbing substitute for git branch
is usually git for-each-ref
.
$ git fetch --prune
$ git for-each-ref --format '%(refname) %(upstream)' refs/heads refs/remotes/origin
This output will include an entry for each local branch, and an entry for each remote tracking ref pointing back to origin; so if run right after fetch --prune
as shown here, it can show you what exists locally but not on the server.
Of course there's a gotcha: "exists locally but not on the server" might mean "removed from the server", or might mean "created locally and not yet pushed". To tell the difference, you need to also know whether your local branch "thinks" it has an upstream. (If it does, it's reasonably safe to assume it was removed from the server, in that git
resists setting a nonexistent upstream; so for it to be wrong, someone would basically have to deliberately "trick" your script with a corrupt configuration.)
So that's what the --format
option is for. You can process this output, looking for
refs/heads/somebranch refs/remotes/origin/somebranch
and, for each such entry, if there's not also a separate entry like
refs/remotes/origin/somebranch
then this is a branch that would be marked [gone]
Building off of Mark's answer, and this post, here's a pretty clean solution (split lines for readability):
git for-each-ref \
--format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' \
refs/heads
"gone" as plumbing message
upstream:track
displaying [gone]
--format
A simple way to use this is with command substitution with git branch -D
. Note that git will complain if there are no branches to delete.
git branch -D $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads)
Here is a slightly longer version where git doesn't complain if there are no branches to delete.
for branch in $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads); do git branch -D $branch; done
Alternatively, you can save the output of git for-each-ref
into a variable, then conditionally delete the branch if it's not empty, or show a message if it is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With