Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

remove branches not on remote

Tags:

git

git-branch

==> git branch -a
* master
  test
  remotes/origin/master
  remotes/origin/test

when someone delete the remotes/origin/test,I still can see it on my computer.

I know I can do this and remove the test

==> git remote prune
==> git branch -d test
==> git branch -a
* master
  remotes/origin/master

But if I have more local branch, and they are not on remote, so how can I remove them quickly?

like image 989
Dozer Avatar asked May 16 '13 14:05

Dozer


People also ask

How do I delete local branches without 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.


8 Answers

This is how I remove local branches that are not longer relevant:

git branch --merged origin/master | xargs git branch -d 

You may need to tweak it according to your specific configuration (e.g. see comments below to exclude particular branches), but the first command here before the pipe should give you a list of all your local branches that have been merged into your master branch.

like image 132
eck Avatar answered Sep 30 '22 06:09

eck


A simple prune will not delete the local branch.

Here is another approach to achieve a real deletion. Be sure to execute "git fetch -p" first to get the latest status of the remote repositories.

git branch -vv | grep ': gone]'|  grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d 

This will check all local branches and their origin and will delete all local branches whose origin was deleted.

In detail:

git branch -vv 

will list your local branches and show information about the remote branch, saying “gone” if it is not present anymore.

grep ': gone]' 

will fetch the branches that match the “ gone]” phrase.

grep -v "\*" 

will fetch only lines that do not contain an asterisk. This will ignore the branch you are currently on and also prevent that the “git branch -d” is executed with a “*” at the end which would result in deleting all your local branches

awk '{print $1}' 

will fetch the output until the first white space, which will result in the local branch name.

xargs git branch -d 

will use the output (branch name) and append it to the “git branch -d” command to finally delete the branch. If you also want to delete branches that are not fully merged, you can use a capital “D” instead of “d” to force delete.

like image 23
kcm Avatar answered Sep 30 '22 05:09

kcm


According to the git-fetch manual page, git fetch -p will "After fetching, remove any remote-tracking branches which no longer exist on the remote.` If you have local branches tracking those remote branches, you may need to prune those manually.

like image 33
twalberg Avatar answered Sep 30 '22 05:09

twalberg


I wrote a simple shell script called git-dangling-branches for this purpose. If you specify -D option, it will delete all local branches which don't have refs/remotes/origin/<branch_name>. Of course, you should be careful when you do that.

#!/bin/bash -e
if [[ "$1" == '-D' ]]; then
  DELETE=1
else
  DELETE=0
fi

REMOTE_BRANCHES="`mktemp`"
LOCAL_BRANCHES="`mktemp`"
DANGLING_BRANCHES="`mktemp`"
git for-each-ref --format="%(refname)" refs/remotes/origin/ | \
  sed 's#^refs/remotes/origin/##' > "$REMOTE_BRANCHES"
git for-each-ref --format="%(refname)" refs/heads/ | \
  sed 's#^refs/heads/##' > "$LOCAL_BRANCHES"
grep -vxF -f "$REMOTE_BRANCHES" "$LOCAL_BRANCHES" | \
  sort -V > "$DANGLING_BRANCHES"
rm -f "$REMOTE_BRANCHES" "$LOCAL_BRANCHES"

if [[ $DELETE -ne 0 ]]; then
  cat "$DANGLING_BRANCHES" | while read -r B; do
    git branch -D "$B"
  done
else
  cat "$DANGLING_BRANCHES"
fi
rm -f "$DANGLING_BRANCHES"
like image 21
trustin Avatar answered Sep 30 '22 07:09

trustin


I ended up with something very similar to kcm's approach. I wanted something that would purge all local branches that were tracking a remote branch, on origin, where the remote branch has been deleted (gone). I did not want to delete local branches that were never set up to track a remote branch (i.e.: my local dev branches). Also I wanted a simple one-liner that just uses git, or other simple CLI tools, rather than writing custom scripts. I ended up using a bit of grep and awk to make this simple command then added it as a alias in my ~/.gitconfig.

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

Here is a git config --global ... command for easily adding this as git prune-branches:

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'

NOTE: As Matteo pointed out in his earlier comment on another answer, use of the -D flag to git branch can be very dangerous. So, in the config command I use the -d option to git branch rather than -D; I use -D in my actual config. I use -D because I don't want to hear Git complain about unmerged branches, I just want them to go away. You may want this functionality as well. If so, simply use -D instead of -d at the end of that config command.

like image 39
Karl Wilbur Avatar answered Sep 30 '22 05:09

Karl Wilbur


Fast

git fetch -p
git branch -v | grep "\[gone\]"

Then manually check and delete branches in the output.


Detailed

The simplest manual solution based on the answers in this thread as well as here, is to remove all remote-tracking references that no longer exist on the remote with

git fetch -p

then see what has been removed from remote-tracking, but is still in your local working tree with

git branch -v

and manually delete branches that have [gone] in the output.

To get a concise list run

git branch -v | grep "\[gone\]"
like image 20
young_souvlaki Avatar answered Sep 30 '22 07:09

young_souvlaki


You can do this by iterating over the refs, I used following command to remove all the local branches which dont have remote branches and it worked. Warning: this operation does a force delete non fully merged branches, use with care.

git branch -D `git for-each-ref --format="%(fieldName)" refs/heads/<branch-name-pattern>`

%(fieldName) = refname:short)

refs/heads/ = can be suffixed if you have a common prefix/suffix in branch names ex: refs/heads/*abc*

Refer this for more information git-for-each-ref(1) Manual Page

like image 28
Laksitha Ranasingha Avatar answered Sep 30 '22 07:09

Laksitha Ranasingha


First, do:

git fetch && git remote prune origin

And then:

git branch -a | grep -v ${$(git branch -a | grep remotes | cut -d/" -f3-)/#/-e} | xargs git branch -D

  • List all remotes without remote/origin prefix: git branch -a | grep remotes | cut -d'/' -f3-
  • Remove all listed from git: git branch -a | grep v ${<all remotes without prefix>/#/-e}
  • Remove from local needs -D cause not all have to be marked as merged. For example, squash and merge in Github does not mark them as merged.
like image 34
Pando85 Avatar answered Sep 30 '22 06:09

Pando85