不再在远程删除本地分支机构

有没有简单的方法来删除所有没有远程等效的本地分支机构?

例:

分支(本地和远程)

  • 产地/主
  • 产地/漏洞修复,一个
  • 产地/漏洞修复-B
  • 产地/漏洞修复-C

本地,我只有一个主分支。 现在我需要处理bug-fix-a ,所以我检查一下,处理它,然后将更改推送到远程。 接下来,我也使用bug-fix-b

分支(本地和远程)

  • 漏洞修复,一个
  • 漏洞修复-B
  • 产地/主
  • 产地/漏洞修复,一个
  • 产地/漏洞修复-B
  • 产地/漏洞修复-C

现在我有本地分支bug-fix-abug-fix-b 。 主分支维护人员将我的更改合并到主,并删除他已经合并的所有分支。

所以现在的状态是:

分支(本地和远程)

  • 漏洞修复,一个
  • 漏洞修复-B
  • 产地/主
  • 产地/漏洞修复-C

现在我想调用一些命令来删除远程仓库中不再显示的分支(这里是bug-fix-abug-fix-b )。

这将是像现有的命令git remote prune origin ,但更像git local prune origin

git remote prune origin跟踪不在远程的分支。

git branch --merged列表已被合并到当前分支的分支。

xargs git branch -d删除标准input中列出的分支。

小心删除由git branch --merged列出的git branch --merged 。 该列表可以包括您不希望删除的master或其他分支。

为了让自己有机会在删除分支之前编辑列表,您可以在一行中执行以下操作:

git branch --merged >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

在命令之后

 git fetch -p 

删除远程引用,当你运行

 git branch -vv 

它会显示'已经'作为远程状态。 例如,

 $ git branch -vv master b900de9 [origin/master: behind 4] Fixed bug release/v3.8 fdd2f4e [origin/release/v3.8: behind 2] Fixed bug release/v3.9 0d680d0 [origin/release/v3.9: behind 2] Updated comments bug/1234 57379e4 [origin/bug/1234: gone] Fixed bug 

所以你可以写一个简单的脚本来删除远程的本地分支:

 git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done 

这些答案中的大部分(包括前6名中的5个)实际上并没有回答原来的问题。 我看了一堆线程, 这个答案似乎是最干净的。 这是一个稍微更彻底的答案:

git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

说明:

通过修剪您的跟踪分支,然后删除显示他们在git branch -vv “走出去”的本地。

笔记:

只有本地的分支不会被触及。 已在远程删除但未合并的分支将显示通知,但不会在本地删除。 如果你想删除这些以及将-d改为-D

似乎解决scheme在这里 – https://stackoverflow.com/a/1072178/133986

简而言之, git remote prune做到这一点

我在这里find了答案: 如何删除已合并的所有git分支?

 git branch --merged | grep -v "\*" | xargs -n 1 git branch -d 

确保我们保持主人

您可以确保master或任何其他分支在第一个之后添加另一个grep不会被删除。 在这种情况下,你会去:

 git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d 

所以,如果我们想保持masterdevelopstaging ,我们会去:

 git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d 

使这个别名

由于时间有点长,您可能需要为您的.zshrc.bashrc添加一个别名。 我叫gbpurgegit branches purge ):

 alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d' 

然后重新加载您的.bashrc.zshrc

 . ~/.bashrc 

要么

 . ~/.zshrc 

删除所有已经合并到master中的分支,但不要尝试删除master本身:

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

或者添加一个别名:

alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"

说明:

git checkout master结帐主分支

git pull origin master确保本地分支已将所有远程更改合并

git fetch -p删除对已被删除的远程分支的引用

git branch -d $(git branch master --merged | grep master -v)删除已经合并到master的所有分支,但是不要尝试删除master本身

 git fetch -p 

这将删除所有未被远程跟踪的分支。

我不认为有一个内置的命令来做到这一点,但是可以安全地执行以下操作:

 git checkout master git branch -d bug-fix-a 

当你使用-d ,git会拒绝删除分支,除非它被完全合并到HEAD或其上游的远程跟踪分支中。 所以,你总是可以遍历git for-each-ref的输出,并尝试删除每个分支。 这种方法的问题是,我怀疑你可能不希望bug-fix-d被删除,只是因为origin/bug-fix-d包含它的历史logging。 相反,你可以创build一个如下所示的脚本:

 #!/bin/sh git checkout master && for r in $(git for-each-ref refs/heads --format='%(refname:short)') do if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ] then if [ "$r" != "master" ] then git branch -d "$r" fi fi done 

警告:我还没有testing过这个脚本 – 只能谨慎使用…

这将删除除本地主引用和当前正在使用的所有合并的本地分支:

 git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d 

这将删除已经从“ origin ”引用的远程存储库中删除的所有分支,但仍在本地“ remotes / origin ”中可用。

 git remote prune origin 

根据以上信息,这对我工作:

 git br -d `git br -vv | grep ': gone] ' | awk '{print $1}' | xargs` 

它在远程删除所有本地分支': gone] '

我不知道多久,但我现在使用git-up,这是照顾的。

我做git up ,它开始跟踪新的分支机构,并删除旧的。

只是要说清楚,这不是开箱即用的git命令 – https://github.com/aanand/git-up

顺便说一句,它也存储了肮脏的树,并使基地刚刚git up

希望这会对某人有用

我想出了这个bash脚本。 它始终保持分支的developqamaster

 git-clear() { git pull -a > /dev/null local branches=$(git branch --merged | grep -v 'develop' | grep -v 'master' | grep -v 'qa' | sed 's/^\s*//') branches=(${branches//;/ }) if [ -z $branches ]; then echo 'No branches to delete...' return; fi echo $branches echo 'Do you want to delete these merged branches? (y/n)' read yn case $yn in [^Yy]* ) return;; esac echo 'Deleting...' git remote prune origin echo $branches | xargs git branch -d git branch -vv } 

这是我用于鱼壳的解决scheme。 testing在Mac OS X 10.11.5fish 2.3.0git 2.8.3

 function git_clean_branches set base_branch develop # work from our base branch git checkout $base_branch # remove local tracking branches where the remote branch is gone git fetch -p # find all local branches that have been merged into the base branch # and delete any without a corresponding remote branch set local for f in (git branch --merged $base_branch | grep -v "\(master\|$base_branch\|\*\)" | awk '/\s*\w*\s*/ {print $1}') set local $local $f end set remote for f in (git branch -r | xargs basename) set remote $remote $f end for f in $local echo $remote | grep --quiet "\s$f\s" if [ $status -gt 0 ] git branch -d $f end end end 

一些注意事项:

确保设置正确的base_branch 。 在这种情况下,我使用develop作为基本分支,但它可以是任何东西。

这部分是非常重要的: grep -v "\(master\|$base_branch\|\*\)" 。 它确保您不会删除主人或您的基本分支。

我使用git branch -d <branch>作为额外的预防措施,以便不删除任何尚未与上游或当前HEAD完全合并的分支。

一个简单的方法来testing是用echo "will delete $f"replacegit branch -d $f echo "will delete $f"

我想我也应该补充一点:使用你自己的风险!

我使用这种方法,所以我可以有更多的控制。

git branch -D $(git branch | grep -v "master" | grep -v "develop")

这是删除没有命名的任何分支: masterdevelop

这是要删除所有不在本地的远程分支(ruby):

 bs = `git branch`.split; bs2 = `git branch -r | grep origin`.split.reject { |b| bs.include?(b.split('/')[1..-1].join('/')) }; bs2.each { |b| puts `git push origin --delete #{b.split('/')[1..-1].join('/')}` } 

解释:

 # local branches bs = `git branch`.split # remote branches bs2 = `git branch -r | grep origin`.split # reject the branches that are present locally (removes origin/ in front) bs2.reject! { |b| bs.include?(b.split('/')[1..-1].join('/')) } # deletes the branches (removes origin/ in front) bs2.each { |b| puts `git push origin --delete #{b.split('/')[1..-1].join('/')}` }