Reputation: 39451
I've been trying to find a way to delete local git branches with no upstream branch, but none of the answers in the linked question worked for me. It seems that they all rely on git branch -vv
outputting gone]
for branches with no remote, but it does not do so for me, and I can't figure out why.
For example, after running get fetch --prune
, git branch -vv
shows the branch rsg/revert
with no [gone]
tag.
rsg/revert af2c4ac81e Remove temporary debug logging
However, there is no corresponding origin/rsg/revert
branch (I already deleted it on Github). Does anyone know why this isn't working?
Edit: I'm using git 2.15.0 on a Mac. I've never had issues with it before.
Upvotes: 9
Views: 1807
Reputation: 273
As mentioned in other answers, the word gone
does not show up if there's no upstream set for the branches.
I fixed this by detecting ]
instead of gone
.
NOTE: This will also delete branches whose commit messages have ]
. So make sure none of the branches you want to keep have it.
git branch -vv | grep -v ']'| grep -v "\*" | awk '{ print $1; }' | xargs git branch -d
Change -d
in the command to -D
if you want to delete unmerged branches too:
git branch -vv | grep -v ']'| grep -v "\*" | awk '{ print $1; }' | xargs git branch -D
Upvotes: 0
Reputation: 665
In case anyone here needs it, the solution I used was a combination of several others answers found on SO.
For the branch that DO have an upstream, the question linked in current question works perfectly.
As for the branch that LACK such upstream, I went with a variation of this answer.
Here is the modified code snippet which I used :
#! /bin/sh
#
# rm-if-gone: remove branches that have a configured upstream
# where the configured upstream no longer exists. Run with
# -f to make it work, otherwise it just prints what it would
# remove.
force=false
case "$1" in
-f) force=true;;
esac
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads); do
# find configured upstream, if any
remote=$(git config --get branch.$branch.remote) || true
# if tracking local branch, skip
if [ "$remote" = . ]; then continue; fi
# if the upstream commit resolves, skip
ucommit=$(git rev-parse "${branch}@{u}" 2>/dev/null) && continue
# upstream is invalid - remove local branch, or print removal
$force && git branch -D $branch || echo "git branch -D $branch"
done
The modification that was done occurs in the first ||
, when we get the remote. In case no remote is found, the linked answer leaves the branch AS IS. That's exactly the case we're interested in, we want to SUPPRESS thewse branch. Therefore, we output true, so the line doesn't end up in an exit code.
Be warned that this solution will suppress ANY branch on local that isn't linked to a remote (this includes branches you started but didn't push yet), so use accordingly, and don't hesitate to run first without the -f
option.
Hoping this helps someone.
Upvotes: 2
Reputation: 487755
Your Git is new enough and you've run git fetch --prune
, so there's only one conclusion left: rsg/revert
has the wrong upstream or no upstream at all.
To see the upstream setting—or get an error if there is none—use git rev-parse
like this (note that some shells may require quoting the curly braces):
git rev-parse --abbrev-ref rsg/revert@{u}
For example:
$ git rev-parse --abbrev-ref master@{u}
origin/master
$ git rev-parse --abbrev-ref dev@{u}
fatal: no upstream configured for branch 'dev'
The upstream of my master
here is origin/master
, but there is no upstream set for my dev
.
The git branch -vv
output will include the word gone
in square brackets if and only if:
So if I somehow delete origin/master
from my own Git repository (which I can do with various Git maintenance commands, or with git branch -d -r origin/master
) I will get:
$ git branch -d -r origin/master
Deleted remote-tracking branch origin/master (was 08da6496b6).
$ git branch -vv
dev 9c9b961d7e The sixth batch
* master 08da6496b6 [origin/master: gone] Eighth batch
(I then ran git fetch
to pick up new commits and re-create my origin/master
, which is now f21f8f5d35
instead of 08da6496b6
.)
Given that you had GitHub delete rsg/revert
and then ran a git fetch -p
that deleted origin/rsg/revert
, your rsg/revert
branch must something else, or nothing, as its upstream.
Upvotes: 7