简体   繁体   English

删除不再在Github上的所有分支

[英]Delete all branches that are no longer on Github

I have branches Branch-Master, Branch-A, Branch-B, Branch-C on GitHub. 我在GitHub上有Branch-Master,Branch-A,Branch-B,Branch-C分支。 I usually merge into master and delete the merged branch. 我通常合并为master并删除合并的分支。 This leaves a bunch of branches on my local machine, but not GitHub. 这在我的本地机器上留下了一堆分支,但不是GitHub。

How do I automatically remove my local branches automatically? 如何自动自动删除本地分支? I want to create a git hook to do this. 我想创建一个git钩子来做到这一点。

When I try 当我尝试

git remote prune origin

and then run git branch, I still see all my branches, even the ones merged and deleted into master. 然后运行git branch,我仍然看到我的所有分支,甚至是那些合并并删除到master中的分支。

I know I can do 我知道我能做到

git branch -d {the_local_branch}

manually, but this does not help when doing a githook or I have multiple branches to remove systematically. 手动,但这在做githook或我有多个分支系统删除时没有帮助。

What I don't like about the answers given here: How can I delete all Git branches which have been merged? 我不喜欢这里给出的答案: 如何删除已合并的所有Git分支?

Is that they are based off names, and inferring the deleted branch, rather than somehow explicitly passing a branch id, specific to that branch. 它们是基于名称,并推断已删除的分支,而不是以某种方式显式传递特定于该分支的分支ID。 What I understand in the link provided, is that if I create a branch name that is the same as the deleted branch, it will also be deleted, even though they are different branches. 我在提供的链接中理解的是,如果我创建一个与已删除分支相同的分支名称,它也将被删除,即使它们是不同的分支。

How do I delete a Git branch locally and remotely? 如何在本地和远程删除Git分支?

Does not address my inquiry, as it's solution is already stated above. 不解决我的询问,因为它的解决方案已在上面说明。

I would rather have some type of compare function using branch uid's if they exist. 如果它们存在,我宁愿使用分支uid的某种类型的比较函数。

You can delete all branches at one go (except the one which is checked out) by one single command: 您可以通过一个命令一次性删除所有分支(除了已签出的分支):

git branch --list | xargs git branch -D

If you want to specify some pattern to match the branch name, you can do that too: 如果要指定某个模式以匹配分支名称,您也可以这样做:

git branch --list k* | xargs git branch -D

And with the help of 并借助于

git remote prune origin

you can delete remote branches in your system that are no longer referenced. 您可以删除系统中不再引用的远程分支。

Hope this helps ! 希望这可以帮助 !

As phd noted in a comment , there is no underlying ID for branches. 正如phd在评论中指出的那样,分支机构没有基础ID A branch name is simply a local name in your repository, created by you or at your request, that identifies one specific commit. 分支名称就是在你的仓库,你或你的请求创建一个本地名称,标识一个具体的承诺。 You can change this name any time, to any string you like as long as it meets the requirements for a branch name . 您可以随时更改此名称,只要它符合分支名称的要求即可更改为您喜欢的任何字符串。 Git won't remember that it used to have some other name. Git不会记得曾经有过其他名字。

Now, there are a few additional bits of information: your .git/config file can, and usually will, have in it, for each branch, some annotations such as: 现在,还有一些额外的信息:你的.git/config文件可以,并且通常会在其中,每个分支,一些注释,如:

[branch "master"]
    remote = origin
    merge = master

[branch "develop"]
    remote = another-remote
    merge = develop

These settings define the upstream setting of the branch. 这些设置定义分支的上游设置 A branch can have no upstream at all—in which case the two settings are non-existent—or one upstream, in which case the two settings exist and describe the upstream, using the two parts from the old historical method of dealing with this before remote-tracking names were invented. 一个分支根本没有上游 - 在这种情况下,两个设置不存在 - 或者一个上游,在这种情况下,两个设置存在并描述上游,使用旧的历史方法处理此前的两个部分发明了远程跟踪名称。

These configuration sections will automatically get renamed if you use standard Git commands to rename the branch. 如果使用标准Git命令重命名分支,则会自动重命名这些配置节。 For instance, after git branch -m develop xyz , you will have: 例如,在git branch -m develop xyz ,你将拥有:

[branch "xyz"]
    remote = another-remote
    merge = develop

which means that the upstream of your local branch xyz is another-remote/develop . 这意味着你的本地分支xyz的上游是another-remote/develop (This assumes a standard fetch = setting for remote another-remote .) (这假定标准fetch =远程another-remote 。)

It's possible, with some effort, to read through the upstream setting (if any) of each branch: use git for-each-ref to enumerate all branches, and then, for each branch, use git rev-parse --symbolic-full-name <branch>@{upstream} to see if it has an upstream, and if so, what the upstream name is. 通过一些努力,可以读取每个分支的上游设置(如果有的话):使用git for-each-ref枚举所有分支,然后,对于每个分支,使用git rev-parse --symbolic-full-name <branch>@{upstream}查看它是否有上游,如果是,上游名称是什么。 Note that you must be a little bit careful here as the "remote" can be set to . 请注意,您必须要小心,因为“远程”可以设置为. , indicating that the upstream of some local branch is another local branch. ,表明某个本地分支的上游是另一个本地分支。

Combining this kind of programmatic test ("does branch X have an upstream, and if so, is it actually a remote-tracking name, and what remote-tracking name is it?") with a second test ("after using git remote <remote> prune or git fetch <remote> --prune , does the remote-tracking name exist?") may get you what you want. 结合这种方案测试的(“确实分支X具有上游,并且如果是这样,它实际上是一个远程跟踪名称,和什么远程跟踪名字什么?”)与第二测试(“用后git remote <remote> prunegit fetch <remote> --prune ,远程跟踪名称是否存在?“)可以得到你想要的。 You'll need to do some coding (bash scripting, for instance). 你需要做一些编码(例如bash脚本)。 Making it optimal, or work from within a hook, is hard, but the overall task is pretty straightforward: 使其最优化,或者在钩子内工作很难,但总体任务非常简单:

git for-each-ref --format='%(refname:short)' refs/heads |
while read branch; do
    # make sure it has an upstream set -- if not, ignore
    upstream=$(git rev-parse --symbolic-full-name ${branch}@{upstream}) || continue
    # make sure the upstream is a remote-tracking name
    case $upstream in
    refs/remotes/*) ;;
    *) continue;;
    esac
    # get the name of the remote
    remote=${upstream#refs/remotes/}
    remote=${remote%%/*}
    # prune remote-tracking branches
    git remote $remote prune
    # and test whether the upstream still exists
    git rev-parse $upstream && continue

    # $branch has upstream $upstream which is gone, so:
    echo git branch -D $branch
done

This is quite untested, and is missing important bits like keeping it quiet about branches it's not going to delete (each rev-parse will spew messages to stdout and/or stderr). 这是非常未经测试的,并且缺少重要的部分,例如保持它不会删除的分支(每个rev-parse将向stdout和/或stderr发送消息)。 It also doesn't actually delete any branches: since that can be rather irrecoverable, so one would want to test it thoroughly first, and only then remove the echo . 它实际上也没有删除任何分支:因为它可能是相当不可恢复的,所以人们首先需要彻底测试它,然后才删除echo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM