我遵循一个开发过程,即为每个新功能或故事卡创建一个新的本地分支。完成后,我合并到主分支,然后推。
随着时间的推移,由于懒惰或健忘,我最终会得到一个很大的本地分支列表,其中一些(如spike)可能还没有合并。
我知道如何列出我所有的本地分支,我知道如何删除一个分支,但我想知道是否有一个git命令,允许我删除我所有的本地分支?
下面是git分支——merged命令的输出。
user@machine:~/projects/application[master]$ git branch --merged
STORY-123-Short-Description
STORY-456-Another-Description
STORY-789-Blah-Blah
* master
所有尝试删除grep -v \*列出的分支(根据下面的答案)都会导致错误:
error: branch 'STORY-123-Short-Description' not found.
error: branch 'STORY-456-Another-Description' not found.
error: branch 'STORY-789-Blah-Blah' not found.
我用的是:
git 1.7.4.1
ubuntu 10.04
GNU bash, version 4.1.5(1)-release
GNU grep 2.5.4
'git branch -d'子命令可以删除多个分支。所以,简化@sblom的答案,但增加了一个关键的xargs:
git branch -D `git branch --merged | grep -v \* | xargs`
或者,进一步简化为:
git branch --merged | grep -v \* | xargs git branch -D
重要的是,正如@AndrewC所指出的,不鼓励使用git分支来编写脚本。要避免使用,可以使用如下语句:
git for-each-ref --format '%(refname:short)' refs/heads | grep -v "master\|main" | xargs git branch -D
删除时要谨慎!
$ mkdir br
$ cd br; git init
Initialized empty Git repository in /Users/ebg/test/br/.git/
$ touch README; git add README; git commit -m 'First commit'
[master (root-commit) 1d738b5] First commit
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README
$ git branch Story-123-a
$ git branch Story-123-b
$ git branch Story-123-c
$ git branch --merged
Story-123-a
Story-123-b
Story-123-c
* master
$ git branch --merged | grep -v \* | xargs
Story-123-a Story-123-b Story-123-c
$ git branch --merged | grep -v \* | xargs git branch -D
Deleted branch Story-123-a (was 1d738b5).
Deleted branch Story-123-b (was 1d738b5).
Deleted branch Story-123-c (was 1d738b5).
如果你不需要使用Git本身,你也可以手动或编程地删除. Git /refs/heads下的头。以下应该在Bash下进行最小的调整:
shopt -s extglob
rm -rf .git/refs/heads/!(master)
这将删除除主分支外的所有本地分支。由于上游分支存储在.git/refs/remotes下,因此它们将保持不变。
如果你不使用Bash,或者想一次递归很多Git存储库,你可以用GNU find做类似的事情:
find . \
-path remotes -path logs -prune -o \
-wholename \*.git/refs/heads/\* \! -name master -print0 |
xargs -0 rm -rf
find解决方案可能更容易移植,但是删除路径和文件名比较棘手,而且可能更容易出错。
不建议解析git分支的输出,这对于Stack Overflow的读者来说不是一个很好的答案。
git branch is what is known as a porcelain command. Porcelain commands are not designed to be machine parsed and the output may change between different versions of Git.
There are user configuration options that change the output of git
branch in a way that makes it difficult to parse (for instance, colorization). If a user has set color.branch then you will get control codes in the output, this will lead to error: branch 'foo' not found. if you attempt to pipe it into another command. You can bypass this with the --no-color flag to git branch, but who knows what other user configurations might break things.
git branch may do other things that are annoying to parse, like
put an asterisk next to the currently checked out branch
git的维护者对围绕git分支输出编写脚本有这样的看法
为了找出当前的分支是什么,随意/粗心的用户可能有
围绕git分支编写脚本,这是错误的。我们积极劝阻
反对使用任何瓷器命令,包括git分支,在
脚本,因为命令的输出可能更改为
帮助人类消费用例。
建议手动编辑. Git目录下的文件(如. Git /refs/heads)的答案同样有问题(refs可能在. Git / packs -refs中,或者Git可能在未来改变它们的内部布局)。
Git提供for-each-ref命令来检索分支列表。
Git 2.7。X将引入——merged选项,这样您就可以执行如下操作来查找并删除合并到HEAD中的所有分支
for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
do
git branch -d ${mergedBranch}
done
Git 2.6。X和更老的版本,您将需要列出所有本地分支,然后分别测试它们,以查看它们是否已经合并(这将显著地慢一些,并且稍微复杂一些)。
for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
do
git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
done
下面的脚本删除分支。使用和修改的风险由你自己承担,等等。
根据这个问题中的其他答案,我最终为自己编写了一个快速bash脚本。我称它为“gitbd”(git branch -D),但如果你使用它,你可以将它重命名为任何你想要的。
gitbd() {
if [ $# -le 1 ]
then
local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
read -n 1 -r # Immediately continue after getting 1 keypress
echo # Move to a new line
if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
then
echo $branches_to_delete | xargs git branch -D
fi
else
echo "This command takes one arg (match pattern) or no args (match all)"
fi
}
它将提供删除任何匹配模式参数的分支(如果传入),或者在不带参数的情况下调用所有本地分支。它还会给你一个确认步骤,因为我们在删除东西,这很好。
这有点愚蠢——如果没有与模式匹配的分支,它就不会意识到这一点。
一个示例输出运行:
$ gitbd test
Matching branches:
dummy+test1
dummy+test2
dummy+test3
Delete? [Y/n]