Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List all local branches without a remote

Tags:

git

git-remote

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 without a remote:

$ git co -b no_upstream 

I list all my branches, and there's only one 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

like image 866
JC Denton Avatar asked Mar 27 '13 14:03

JC Denton


People also ask

How do you remove all branches that are not on remote?

Remove All Local Branches not on Remote First we get all remote branches using the git branch -r command. Next, we get the local branches not on the remote using the egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) command, Finally we delete the branches using the xargs git branch -d command.

How do I find the code of all branches?

Git includes a grep command to search through commits to a repo as well as the local files in the repo directory: git grep. Sometimes it is useful to search for a string throughout an entire repo, e.g. to find where an error message is produced.


1 Answers

I recommend using git branch --format to specify the exact output you want from the git branch command. By doing that, you can pull out just the refname and the upstream, like this:

git branch --format "%(refname:short) %(upstream)" 

It outputs the branches along with the remote branches if they exist, in the following format:

25-timeout-error-with-many-targets 31-target-suggestions refs/remotes/origin/31-target-suggestions 54-feedback-link refs/remotes/origin/54-feedback-link 65-digest-double-publish 

Once you have this nicely formatted output, it's as easy as piping it through awk to get your list:

git branch --format "%(refname:short) %(upstream)" | awk '{if (!$2) print $1;}' 

Results in the following output:

25-timeout-error-with-many-targets 65-digest-double-publish 

The awk portion prints the first column if there is no second column.

Bonus: Create an alias

Make it easy to run by creating an alias in your global .gitconfig file (or wherever):

[alias]   local-branches = "!git branch --format '%(refname:short) %(upstream:short)' | awk '{if (!$2) print $1;}'" 

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 add the remote name to the awk pattern. In my case, it's origin so I can do this:

git branch --format "%(refname:short) %(upstream)" | awk '$2 !~/\/origin\// { print $1 }' 

Important: The backslash needs to be escaped in the alias or else you will have an invalid gitconfig file.


Previous Answer

The previous answer was functionally similar, but used the following as it's starting point. Over time, commenters have pointed out that a regex is unreliable due to the variance possible in a commit message, so I no longer recommend this method. But, here it is for reference:

I recently discovered git branch -vv which is the "very verbose" version of the git branch command.

It outputs the branches along with the remote branches if they exist, in the following format:

  25-timeout-error-with-many-targets    206a5fa WIP: batch insert   31-target-suggestions                 f5bdce6 [origin/31-target-suggestions] Create target suggestion for team and list on save * 54-feedback-link                      b98e97c [origin/54-feedback-link] WIP: Feedback link in mail   65-digest-double-publish              2de4150 WIP: publishing-state 

Once you have this nicely formatted output, it's as easy as piping it through cut and awk to get your list:

git branch -vv | cut -c 3- | awk '$3 !~/\[/ { print $1 }' 
like image 108
Jeremy Baker Avatar answered Nov 15 '22 23:11

Jeremy Baker