Problem: I want a way of deleting all the local branches I have that do not have a remote. It's easy enough to pipe the names of the branches into a git branch -D {branch_name}
, but how do I get that list in the first place?
For example:
I create a new branch with no remote:
$ git co -b no_upstream
I list all my branches, there's only 1 with a remote
$ git branch -a
master
* no_upstream
remotes/origin/HEAD -> origin/master
remotes/origin/master
What command can I run to get no_upstream
as an answer?
I can run git rev-parse --abbrev-ref --symbolic-full-name @{u}
and that will show that it has no remote:
$ git rev-parse --abbrev-ref --symbolic-full-name @{u}
error: No upstream configured for branch 'no_upstream'
error: No upstream configured for branch 'no_upstream'
fatal: ambiguous argument '@{u}': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
But as this is an error, it won't let me use it or pipe it to other commands. I'm intending to use this as either a shell script alias'd to git-delete-unbranched
or maybe make a super simple Gem like git-branch-delete-orphans
Any help would be appreciated! Thanks
I recently discovered
git branch -vv
which is the "very verbose" version of thegit branch
command.It outputs the branches along with the remote branches if they exist, in the following format:
Once you have this nicely formatted output, it's as easy as piping it through
cut
andawk
to get your list:Results in the following output:
The
cut
portion just normalizes the data by removing the first two characters (including*
) from the output before passing it toawk
.The
awk
portion prints the first column if there is no square bracket in the third column.Bonus: Create an alias
Make it easy to run by creating an alias in your global
.gitconfig
file (or wherever):Important: The backslash needs to be escaped in the alias or else you will have an invalid gitconfig file.
Bonus: Remote Filtering
If for some reason you have multiple tracking remotes for different branches, it's easy enough to specify which remote you want to check against. Just append the remote name to the awk pattern. In my case, it's
origin
so I can do this:I have a similar issue. I want to remove all local branches that were tracking remote branches that are now deleted. I am finding that
git remote prune origin
was insufficient to remove the branches that I want gone. Once the remote is deleted, I want the local to go away too. Here is what worked for me:From my
~/.gitconfig
:EDIT: As requested, here is a
git config --global ...
command for easily adding this asgit prune-branches
:NOTE: I changed the
-d
to-D
in my actual config because I don't want to hear Git complain about unmerged branches. You may want this functionality as well. If so, simply use-D
instead of-d
at the end of that command.Also, FWIW, your global config file would almost always be
~/.gitconfig
.EDIT:(OSX Fix) As written, this does not work on OSX because of the use of
xargs -r
(thanks, Korny).The
-r
is to preventxargs
from runninggit branch -d
with no branch name, which will result in an error message "fatal: branch name required
". If you don't mind the error message, you can simply remove the-r
argument toxargs
and you're all set.However, if you don't want to see an error message (and really, who could blame you) then you'll need something else that checks for an empty pipe. If you might be able to use ifne from moreutils. You would insert
ifne
beforexargs
, which will stopxargs
from running with empty data. NOTE:ifne
considers anything to be not empty, this includes blank lines, so you may still see that error message. I've not tested this on OSX.Here is that
git config
line withifne
:Rough powershell implementation: (if origin is your only remote)
git branch
(without any options) lists only local branches, but you don't know if they are tracking a remote branch or not.Usually those local branches should be deleted once merged into
master
(as seen in this issue of git-sweep):This isn't as complete as you want, but it is a start.
Here is something I have used in PowerShell with comments to explain what it's doing. In an attempt to make it clear what's going on, I've not used any abbreviated PS commands. Feel free to compress it to your desired level of crypticness :)
I sinthetize my own git command to get the
origin/***: gone
branches:git remote prune origin && git branch -vv
will print branches in verbose modecut -c 3-
will remove very first charsgrep ': gone]'
will print only the gone remote branchesawk '{print $1}'
will print the branch namexargs -n1 -r echo git branch -d
will print thegit branch -d
command to remove branches (-n1 will manage one command per time, -r to avoid issuing command if no branch is present)HINT: remove the "echo" command to run the commands instead of print only, I left this in the command to check commands before issuing to git.
HINT 2: issue
git branch -D
if and only if you are sure you want to remove unmerged branches