Discussion:
Find/prune local branches after upstream branch is deleted?
Jed Brown
2013-04-19 17:11:38 UTC
Permalink
Consider this workflow:

$ git checkout -b my/branch
hack, commit, ...
$ git push -u origin my/branch

The branch gets reviewed, merged, and eventually deleted upstream. The
remote tracking branch gets pruned via 'git fetch --prune' or 'git
remote prune', but that leaves my local branch with an upstream that has
been deleted. Is there a good way to discover this so I can prune my
local branches?

$ git branch -vv
my/branch 6d32ec0 [origin/my/branch] The commit message

I can script it, but this seems like a pretty common thing.
Jeff King
2013-04-19 17:37:17 UTC
Permalink
Post by Jed Brown
$ git checkout -b my/branch
hack, commit, ...
$ git push -u origin my/branch
The branch gets reviewed, merged, and eventually deleted upstream. The
remote tracking branch gets pruned via 'git fetch --prune' or 'git
remote prune', but that leaves my local branch with an upstream that has
been deleted. Is there a good way to discover this so I can prune my
local branches?
$ git branch -vv
my/branch 6d32ec0 [origin/my/branch] The commit message
I can script it, but this seems like a pretty common thing.
Try "git branch --merged master" to get a list of branches that have
already been merged.

-Peff
Jed Brown
2013-04-19 17:50:48 UTC
Permalink
Post by Jeff King
Try "git branch --merged master" to get a list of branches that have
already been merged.
That's what I use, but I was hoping for something more precise. For
example, a branch that started at 'maint' would show up there, but its
integration hasn't completed until it makes it back to 'maint'.
Jeff King
2013-04-19 18:05:20 UTC
Permalink
Post by Jed Brown
Post by Jeff King
Try "git branch --merged master" to get a list of branches that have
already been merged.
That's what I use, but I was hoping for something more precise. For
example, a branch that started at 'maint' would show up there, but its
integration hasn't completed until it makes it back to 'maint'.
Yeah, git has no way of knowing that. You can tell it by asking "git
branch --merged maint" and looking for such topics, of course, but I
think you are trying to remove as much thinking as possible from the
process.

So what is the clue that you would like to use to know that the branch
is stale. Deletion of the branch on the remote?

For that, I don't think there is a single command. You can do "git push
--dry-run --all" and look for new branches that would be pushed, but
that is kind of hacky. The answer you want is:

comm -23 \
<(git for-each-ref --format='%(refname:short)' refs/heads) \
<(git for-each-ref --format='%(refname:short)' refs/remotes/origin |
sed s,origin/,,)

You said you didn't want to script, but I think that is the only option
to answer that question cleanly.

Note that if you wrap that in an alias, you would want to use "bash -c",
as the <() syntax is not understood by many /bin/sh implementations.

-Peff
Jed Brown
2013-04-19 19:30:32 UTC
Permalink
Post by Jeff King
Post by Jed Brown
Post by Jeff King
Try "git branch --merged master" to get a list of branches that have
already been merged.
That's what I use, but I was hoping for something more precise. For
example, a branch that started at 'maint' would show up there, but its
integration hasn't completed until it makes it back to 'maint'.
Yeah, git has no way of knowing that. You can tell it by asking "git
branch --merged maint" and looking for such topics, of course, but I
think you are trying to remove as much thinking as possible from the
process.
So what is the clue that you would like to use to know that the branch
is stale. Deletion of the branch on the remote?
I was hoping for ("has an upstream set" AND "upstream branch deleted").
Post by Jeff King
For that, I don't think there is a single command. You can do "git push
--dry-run --all" and look for new branches that would be pushed, but
comm -23 \
<(git for-each-ref --format='%(refname:short)' refs/heads) \
<(git for-each-ref --format='%(refname:short)' refs/remotes/origin |
sed s,origin/,,)
This also finds my private branches that I just haven't pushed yet. The
following has what I think are good semantics.

git for-each-ref --format='%(refname:short) %(upstream)' refs/heads |
while read ref upstream; do
test -n "$upstream" && (git show-ref -q --verify "$upstream" || echo $ref)
done


FWIW, Git sorts non-alpha characters differently from 'sort'. This
means that Git output can't be sent to comm without first '| sort'.

$ git branch xy
$ git branch x-y
$ git branch
* master
x-y
xy
$ git branch | sort
* master
xy
x-y

Loading...