简体   繁体   English

如何修剪远程不再存在的本地跟踪分支

[英]How to prune local tracking branches that do not exist on remote anymore

With git remote prune origin I can remove the local branches that are not on the remote any more.使用git remote prune origin我可以删除不在远程的本地分支。

But I also want to remove local branches that were created from those remote branches (a check if they are unmerged would be nice).但我也想删除从那些远程分支创建的本地分支(检查它们是否未合并会很好)。

How can I do this?我怎样才能做到这一点?

After pruning, you can get the list of remote branches with git branch -r .剪枝后,可以通过git branch -r获取远程分支列表。 The list of branches with their remote tracking branch can be retrieved with git branch -vv .可以使用git branch -vv检索具有远程跟踪分支的分支列表。 So using these two lists you can find the remote tracking branches that are not in the list of remotes.因此,使用这两个列表,您可以找到不在远程列表中的远程跟踪分支。

This line should do the trick (requires bash or zsh , won't work with standard Bourne shell):这条线应该可以解决问题(需要bashzsh ,不适用于标准 Bourne shell):

git fetch -p ; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

This string gets the list of remote branches and passes it into egrep through the standard input.此字符串获取远程分支列表并通过标准输入将其传递给egrep And filters the branches that have a remote tracking branch (using git branch -vv and filtering for those that have origin ) then getting the first column of that output which will be the branch name.并过滤具有远程跟踪分支的分支(使用git branch -vv并过滤具有origin的分支),然后获取该输出的第一列,这将是分支名称。 Finally passing all the branch names into the delete branch command.最后将所有分支名称传递给删除分支命令。

Since it is using the -d option, it will not delete branches that have not been merged into the branch that you are on when you run this command.由于它使用-d选项,因此在运行此命令时,它不会删除尚未合并到您所在分支的分支。

If you want to delete all local branches that are already merged into master, you can use the following command:如果要删除所有已经合并到master的本地分支,可以使用如下命令:

git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

If you are using main as your master branch, you should modify the command accordingly:如果你使用main作为你的主分支,你应该相应地修改命令:

git branch --merged main | grep -v '^[ *]*main$' | xargs git branch -d

More info . 更多信息

Amidst the information presented by git help fetch , there is this little item:git help fetch提供的信息中,有一个小项目:

 -p, --prune
        After fetching, remove any remote-tracking branches which no longer exist on the remote.

So, perhaps, git fetch -p is what you are looking for?所以,也许, git fetch -p是你在找什么?

EDIT: Ok, for those still debating this answer 3 years after the fact, here's a little more information on why I presented this answer...编辑:好的,对于那些在事实发生 3 年后仍在争论这个答案的人,这里有更多关于我为什么提出这个答案的信息......

First, the OP says they want to "remove also those local branches that were created from those remote branches [that are not any more on the remote]".首先,OP 说他们想“删除那些从那些远程分支创建的本地分支[不再在远程]”。 This is not unambiguously possible in git .这在git中并非毫无疑问是可能的。 Here's an example.这是一个例子。

Let's say I have a repo on a central server, and it has two branches, called A and B .假设我在中央服务器上有一个 repo,它有两个分支,称为AB If I clone that repo to my local system, my clone will have local refs (not actual branches yet) called origin/A and origin/B .如果我将该 repo 克隆到我的本地系统,我的克隆将具有称为origin/Aorigin/B的本地引用(还不是实际的分支)。 Now let's say I do the following:现在假设我执行以下操作:

git checkout -b A origin/A
git checkout -b Z origin/B
git checkout -b C <some hash>

The pertinent facts here are that I for some reason chose to create a branch on my local repo that has a different name than its origin, and I also have a local branch that does not (yet) exist on the origin repo.这里的相关事实是,出于某种原因,我选择在本地存储库上创建一个名称与其来源不同的分支,并且我还有一个本地分支(尚不存在于原始存储库中)。

Now let's say I remove both the A and B branches on the remote repo and update my local repo ( git fetch of some form), which causes my local refs origin/A and origin/B to disappear.现在假设我删除了远程仓库上的AB分支并更新了我的本地仓库(某种形式的git fetch ),这会导致我的本地引用origin/Aorigin/B消失。 Now, my local repo has three branches still, A , Z , and C .现在,我的本地仓库仍然有三个分支, AZC None of these have a corresponding branch on the remote repo.这些都没有远程仓库上的相应分支。 Two of them were "created from ... remote branches", but even if I know that there used to be a branch called B on the origin, I have no way to know that Z was created from B , because it was renamed in the process, probably for a good reason.其中两个是“从...远程分支创建的”,但是即使我知道在原点上曾经有一个名为B的分支,我也无法知道Z是从B创建的,因为它在这个过程,可能是有充分理由的。 So, really, without some external process recording branch origin metadata, or a human who knows the history, it is impossible to tell which of the three branches, if any, the OP is targeting for removal.所以,真的,如果没有一些外部进程记录分支起源元数据,或者没有一个知道历史的人,就不可能分辨出三个分支中的哪一个,如果有的话,OP 的目标是删除。 Without some external information that git does not automatically maintain for you, git fetch -p is about as close as you can get, and any automatic method for literally attempting what the OP asked runs the risk of either deleting too many branches, or missing some that the OP would otherwise want deleted.如果没有一些git不会自动为您维护的外部信息, git fetch -p几乎是您所能获得的,并且任何用于逐字尝试 OP 要求的自动方法都有删除太多分支或丢失一些分支的风险否则OP会希望删除。

There are other scenarios, as well, such as if I create three separate branches off origin/A to test three different approaches to something, and then origin/A goes away.还有其他场景,例如,如果我在origin/A之外创建三个单独的分支来测试对某事物的三种不同方法,然后origin/A消失。 Now I have three branches, which obviously can't all match name-wise, but they were created from origin/A , and so a literal interpretation of the OPs question would require removing all three.现在我有三个分支,显然不能全部匹配名称,但它们是从origin/A创建的,因此对 OPs 问题的字面解释需要删除所有三个。 However, that may not be desirable, if you could even find a reliable way to match them...但是,这可能是不可取的,如果您甚至可以找到一种可靠的方法来匹配它们......

This will delete the local branches for which the remote tracking branches have been pruned.这将删除已修剪远程跟踪分支的本地分支。 (Make sure you are on master branch!) (确保你在master分支上!)

git checkout master
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -d

Details:细节:

  • git branch -vv displays "gone" for local branches that the remote has been pruned. git branch -vv显示远程已被修剪的本地分支“已消失”。

     mybranch abc1234 [origin/mybranch: gone] commit comments
  • -d will check if it has been merged ( -D will delete it regardless) -d将检查它是否已被合并( -D无论如何都会删除它)

     error: The branch 'mybranch' is not fully merged.

There's a neat npm package that does it for you (and it should work cross platform).有一个简洁的 npm 包可以为你做这件事(它应该可以跨平台工作)。

Install it with: npm install -g git-removed-branches安装它: npm install -g git-removed-branches

And then git removed-branches will show you all the stale local branches, and git removed-branches --prune to actually delete them.然后git removed-branches将显示所有陈旧的本地分支,并git removed-branches --prune实际删除它们。

More info here.更多信息在这里。

Windows Solution视窗解决方案

For Microsoft Windows Powershell:对于 Microsoft Windows Powershell:

git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}

Explaination解释

git checkout master switches to the master branch git checkout master切换到 master 分支

git remote update origin --prune prunes remote branches git remote update origin --prune修剪远程分支

git branch -vv gets a verbose output of all branches ( git reference ) git branch -vv获取所有分支的详细输出( git reference

Select-String -Pattern ": gone]" gets only the records where they have been removed from remote. Select-String -Pattern ": gone]"仅获取已从远程删除的记录。

% { $_.toString().Split(" ")[0]} get the branch name % { $_.toString().Split(" ")[0]}获取分支名称

% {git branch -d $_} deletes the branch % {git branch -d $_}删除分支

One can configure Git to automatically remove references to deleted remote branches when fetching:可以将 Git 配置为在获取时自动删除对已删除远程分支的引用:

git config --global fetch.prune true

When calling git fetch or git pull afterwards, references to deleted remote branches get removed automatically.之后调用git fetchgit pull时,对已删除远程分支的引用会自动删除。

As @tzacks notes... there is an npm package that is handy for this.正如@tzacks 所指出的......有一个 npm 包可以方便地解决这个问题。 Just do:做就是了:

npx git-removed-branches --prune

(I would have commented but not enough reputation) (我会评论但没有足够的声誉)

It will list the local branches whose remote tracking branch is deleted from remote它将列出从远程删除其远程跟踪分支的本地分支

$ git remote prune origin --dry-run

If you want to de-reference these local branches from local which are un tracked如果您想从本地取消引用这些未跟踪的本地分支

$ git remote prune origin

Even shorter and safer one-liner:更短、更安全的单线:

git branch -d $(git branch --merged | cut -c 3- | grep -v master)

Be sure to checkout to branch that is not merged yet, before run it.在运行它之前,一定要检查到尚未合并的分支。 Because you can not delete branch that you are currently checked in.因为您无法删除当前签入的分支。

If using Windows and Powershell, you can use the following to delete all local branches that have been merged into the branch currently checked out:如果使用 Windows 和 Powershell,您可以使用以下命令删除所有已合并到当前签出分支的本地分支:

git branch --merged | ? {$_[0] -ne '*'} | % {$_.trim()} | % {git branch -d $_}

Explanation解释

  • Lists the current branch and the branches that have been merged into it列出当前分支和已合并到其中的分支
  • Filters out the current branch过滤掉当前分支
  • Cleans up any leading or trailing spaces from the git output for each remaining branch name清除git输出中每个剩余分支名称的任何前导或尾随空格
  • Deletes the merged local branches删除合并的本地分支

It's worth running git branch --merged by itself first just to make sure it's only going to remove what you expect it to.值得首先运行git branch --merged ,以确保它只会删除您期望的内容。

(Ported/automated from http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/ .) (从http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/移植/自动化。)

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 ).我想要一些东西可以清除所有跟踪远程分支的本地分支,在origin ,远程分支已被删除( gone )。 I did not want to delete local branches that were never set up to track a remote branch (ie: 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.另外,我想要一个简单的单行程序,它只使用git或其他简单的 CLI 工具,而不是编写自定义脚本。 I ended up using a bit of grep and awk to make this simple command, then added it as an alias in my ~/.gitconfig .我最终使用了一些grepawk来制作这个简单的命令,然后将它作为别名添加到我的~/.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 ...命令,可以轻松地将其添加为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: Use of the -D flag to git branch can be very dangerous.注意:在git branch中使用-D标志可能非常危险。 So, in the config command above I use the -d option to git branch rather than -D ;因此,在上面的配置命令中,我使用-d选项来git branch而不是-D I use -D in my actual config.我在我的实际配置中使用-D I use -D because I don't want to hear Git complain about unmerged branches, I just want them to go away.我使用-D是因为我不想听到 Git 抱怨未合并的分支,我只想让它们消失。 You may want this functionality as well.您可能也需要此功能。 If so, simply use -D instead of -d at the end of that config command.如果是这样,只需在该配置命令的末尾使用-D而不是-d

Here is my solution :这是我的解决方案:

git fetch -p
git branch -vv | grep ": gone" | awk '{print $1}' | xargs git branch -d
  • -p is to remove any remote-tracking references that no longer exist on the remote. -p是删除远程不再存在的任何远程跟踪引用。 So first step will remove references to remote branches.所以第一步将删除对远程分支的引用。

  • -vv is for showing sha1 and commit subject line for each head, along with relationship to upstream branch (if any). -vv用于显示每个头的 sha1 和提交主题行,以及与上游分支的关系(如果有)。 2nd step will get all the local branches and grep command will filter out branches that have been deleted.第二步将获取所有本地分支,grep 命令将过滤掉已删除的分支。

There doesn't seem to be a safe one-liner, too many edge cases (like a branch having "master" as part of its name, etc).似乎没有一个安全的单线,太多的边缘情况(比如一个分支有“master”作为它的名字的一部分,等等)。 Safest is these steps:最安全的是这些步骤:

  1. git branch -vv | grep 'gone]' > stale_branches.txt
  2. view the file and remove lines for branches you want to keep (such as master branch!);查看文件并删除要保留的分支的行(例如 master 分支!); you don't need to edit the contents of any line您无需编辑任何行的内容
  3. awk '{print $1}' stale_branches.txt | xargs git branch -d

To remove remote branches:要删除远程分支:

$git remote prune origin

To remove local branches that are already merged:要删除已合并的本地分支:

$git branch -D $(git branch --merged)

Powershell中:

git branch -D (git branch --merged |% { $_.trim() } )

Based on the answers above I'm using this shorter one liner:根据上面的答案,我正在使用这个较短的一个班轮:

git remote prune origin | awk 'BEGIN{FS="origin/"};/pruned/{print $2}' | xargs -r git branch -d

Also, if you already pruned and have local dangling branches, then this will clean them up:此外,如果您已经修剪并有本地悬垂的分支,那么这将清理它们:

git branch -vv | awk '/^ .*gone/{print $1}' | xargs -r git branch -d

not sure how to do it all at once, but git git branch -d <branchname> will delete a local branch ONLY if it is completely merged.不确定如何一次完成所有操作,但 git git branch -d <branchname>只有在完全合并时才会删除本地分支。 Note the lowercase d.注意小写d。

git branch -D <branchname> (note the capital D) will delete a local branch regardless of its merged status. git branch -D <branchname> (注意大写的 D)将删除本地分支,无论其合并状态如何。

Schleis' variant does not work for me (Ubuntu 12.04), so let me propose my (clear and shiny :) variants: Schleis 的变体对我不起作用(Ubuntu 12.04),所以让我提出我的(清晰而闪亮的 :) 变体:

Variant 1 (I would prefer this option):变体 1(我更喜欢这个选项):

git for-each-ref --format='%(refname:short) %(upstream)' refs/heads/ | awk '$2 !~/^refs\/remotes/' | xargs git branch -D 

Variant 2:变体 2:

a.一个。 Dry-run:试运行:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | awk '{print "git branch -D " $1}'

b.湾。 Remove branches:删除分支:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | xargs git branch -D

You can use this command:你可以使用这个命令:

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

Git Clean: Delete Already-Merged Branches including break down of command Git Clean:删除已经合并的分支,包括命令分解

This command and the script below work in Linux and Windows with Git Bash (MinGW).此命令和下面的脚本在 Linux 和 Windows 中使用 Git Bash (MinGW) 工作。

It is best to use git's internal commands so that comments or names don't accidentally match and delete a branch that you don't want to delete.最好使用 git 的内部命令,以免注释或名称意外匹配并删除您不想删除的分支。 There are many internal "atoms" that can be used with git for-each-ref 's format option to output the desired information.有许多内部“原子”可以与git for-each-ref的格式选项一起使用来输出所需的信息。 This way we don't have to rely on piping to awk or grep to check a regular expression on output that may contain unnecessary information.这样我们就不必依赖于awkgrep的管道来检查输出中可能包含不必要信息的正则表达式。

The command below uses only git for-each-ref 's internal low level commands to list only orphaned local branches.下面的命令仅使用git for-each-ref的内部低级命令来仅列出孤立的本地分支。 Once you have these you can pipe to git branch -D .一旦有了这些,您就可以通过管道传输到git branch -D Also, don't forget to prune and fetch your remote references first, or it won't find any matches:另外,不要忘记先修剪并获取远程引用,否则它将找不到任何匹配项:

git fetch -p
git for-each-ref --format '%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' 'refs/heads/**' | xargs -r git branch -D

Here is a breakdown:这是一个细分:

git fetch -p - prune removed references and fetch new ones from the remote git fetch -p - 修剪删除的引用并从远程获取新的

git for-each-ref --format - lists all references using a specific output format. git for-each-ref --format - 使用特定输出格式列出所有引用。

%(if:equals=[gone])%(upstream:track) - only output if the upstream tracking branch is "[gone]". %(if:equals=[gone])%(upstream:track) - 仅在上游跟踪分支为“[gone]”时输出。

%(then)%(refname:short)%(end) - output the branch name (when tracking is gone). %(then)%(refname:short)%(end) - 输出分支名称(当跟踪消失时)。

refs/heads/** - limit to head references (for efficiency). refs/heads/** - 限制头部引用(为了提高效率)。

| xargs -r git branch -D | xargs -r git branch -D - pipe output as parameters for deletion. | xargs -r git branch -D - 管道输出作为删除参数。 The -r indicates to ignore blank input. -r表示忽略空白输入。


By itself, this solution is long, ridiculous to type, and hard to remember.就其本身而言,这个解决方案很长,打字很荒谬,而且很难记住。 Luckily, adding custom commands to git is easy.幸运的是,向 git 添加自定义命令很容易。 Below is a script that uses the same command above, but it allows the user to see which branches will be selected with a --dry-run option.下面是一个使用上述相同命令的脚本,但它允许用户使用--dry-run选项查看将选择哪些分支。

I named my file git-prune-local and dropped it in a folder that was included on my PATH .我将我的文件命名为git-prune-local并将其放入包含在我的PATH中的文件夹中。 It also needs execution permissions ( chmod 755 git-prune-local ).它还需要执行权限( chmod 755 git-prune-local )。

Git automatically looks for executable files like git-[command] . Git 会自动查找可执行文件,例如git-[command] With this, you only need to type git prune-local for the correct branches to be deleted.有了这个,你只需要输入git prune-local来删除正确的分支。

git-prune-local git-prune-本地

#!/bin/sh

if [ $# -gt 1 ] || ([ ! -z $1 ] && [ $1 != "--dry-run" ])
then
    echo "Usage: git prune-local [--dry-run]"
    exit
fi

git fetch -p --quiet
branchesToDelete=$(git for-each-ref --format '%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' 'refs/heads/**')

while read -r branch
do
    if [ ! -z $branch ]
    then
        if [ ! -z $1 ]
        then
            echo $branch
        else
            git branch -D $branch
        fi
    fi
done <<< "$branchesToDelete"

根据上面的答案,我提出了这一行解决方案:

git remote prune origin; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

Using a variant on @wisbucky's answer, I added the following as an alias to my ~/.gitconfig file:使用@wisbucky 答案的变体,我将以下内容作为别名添加到我的~/.gitconfig文件中:

pruneitgood = "!f() { \
    git remote prune origin; \
    git branch -vv | perl -nae 'system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}'; \
}; f"

With this, a simple git pruneitgood will clean up both local & remote branches that are no longer needed after merges.有了这个,一个简单的git pruneitgood将清理合并后不再需要的本地和远程分支。

Following is an adaptation of @wisbucky's answer for Windows users:以下是对 Windows 用户的@wisbucky 答案的改编:

for /f "tokens=1" %i in ('git branch -vv ^| findstr ": gone]"') DO git branch %i -d

I use posh-git and unfortunately PS doesn't like the naked for , so I created a plain 'ol command script named PruneOrphanBranches.cmd:我使用 posh-git,不幸的是 PS 不喜欢裸for ,所以我创建了一个名为 PruneOrphanBranches.cmd 的普通 'ol 命令脚本:

@ECHO OFF
for /f "tokens=1" %%i in ('git branch -vv ^| findstr ": gone]"') DO CALL :ProcessBranch %%i %1

GOTO :EOF

:ProcessBranch
IF /I "%2%"=="-d" (
    git branch %1 %2
) ELSE (
    CALL :OutputMessage %1
)
GOTO :EOF

:OutputMessage
ECHO Will delete branch [%1] 
GOTO :EOF

:EOF

Call it with no parameters to see a list, and then call it with "-d" to perform the actual deletion or "-D" for any branches that are not fully merged but which you want to delete anyway.不带参数调用它以查看列表,然后使用“-d”调用它以执行实际删除或“-D”用于未完全合并但无论如何要删除的任何分支。

The Powershell Version of git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d Powershell 版本的git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

git branch --merged master | %{ if($_ -notmatch '\*.*master'){ git branch -d "$($_.Trim())" }}

This will remove any local branches that have been merged into master, while you are on the master branch .当您在 master 分支上时,这将删除任何已合并到 master 中的本地分支

git checkout master to switch. git checkout master切换。

This works for me using git 2.21.0 - it deletes local tracking branches which are merged into HEAD where I have previously --set-upstream on push (I use push.default=upstream because it works best with multiple remotes) and that upstream branch has since been deleted by a fetch --prune (or implicitly if fetch.prune=true in git config):这适用于我使用 git 2.21.0 - 它删除合并到HEAD中的本地跟踪分支,我之前在推送时--set-upstream (我使用push.default=upstream因为它最适合多个遥控器)和上游分支已被fetch --prune删除(或者如果fetch.prune=true在 git config 中隐式删除):

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

The use of --merged and -d make this a very 'safe' delete.使用--merged-d使其成为非常“安全”的删除。 A more aggressive version could drop the --merged and use -D更激进的版本可能会放弃--merged并使用-D

Try this in git bash, to fetch and prune references to deleted branches, and then prune the local branches that were tracking the removed ones:在 git bash 中尝试此操作,以获取和修剪对已删除分支的引用,然后修剪跟踪已删除分支的本地分支:

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

Remember to checkout first a branch that won't be deleted, so that does not block the deleting of the branch.记得先签出一个不会被删除的分支,这样就不会阻止删除分支。

You can do this by a few simple actions:您可以通过几个简单的操作来做到这一点:

  • Output your all branches into a temp file: Output 你所有的分支到一个临时文件中:
git branch > branches.tmp
  • Open the file and remove branches to exclude them from being deleted from your local (branches like develop / master / main / ... )打开文件并删除分支以排除它们从本地删除(分支如develop / master / main / ...
  • Pass branches name to xargs by cat command and remove branches:通过cat命令将分支名称传递给xargs并删除分支:
cat branches.tmp | xargs git branch -D

On OS X, which supports cut -w在支持cut -w的 OS X 上

git branch -d $(git branch -vv | grep ': gone]' | cut -w -f 2 )

explanation解释

delete following branches删除以下分支
git branch -d ...

show removed branches显示删除的分支

$ git branch -vv | grep ': gone]'
  chore/TECH-456   a4bdac8ac8 [origin/TECH-456: gone] chore: syntax error
  feature/TECH-678 0342f8e277 [origin/feature/TECH-678: gone] Added IsGross in new Income Details

keep the branch name保留分支名称

$ git branch -vv | grep ': gone]' | cut -w -f 2
chore/TECH-456
feature/TECH-678

I have turned the accepted answer into a robust script.我已经把接受的答案变成了一个健壮的脚本。 You'll find it in my git-extensions repository .您可以在我的 git-extensions 存储库中找到它。

$ git-rprune --help
Remove old local branches that do not exist in REMOTE any more.
With --test, only print which local branches would be deleted.
Note: To do this automatically on each fetch / pull:
    git config --global fetch.prune true
Usage: git-rprune REMOTE [-t|--test|-f|--force] [-?|-h|--help]

I reached this page seeking the answer for "how do I delete locally checked out branches that no longer have an upstream branch"我到达此页面寻求“如何删除不再具有上游分支的本地签出分支”的答案

I also did not care whether or not the local branch had been merged in yet, since piping into git branch -d will simply warn instead of deleting unmerged local branches.我也不关心本地分支是否已合并,因为管道进入git branch -d只会发出警告,而不是删除未合并的本地分支。

git branch -a | grep origin | tr -s ' ' | cut -d '/' -f3 | egrep -v -f /dev/fd/0 <(git branch -a | grep -v origin) | grep branch_prefix_that_I_care_about | xargs git branch -d

# translation
# git branch -a | grep origin | tr -s ' ' | cut -d '/' -f3
## this finds all remote branch names minus the "remote/origin/" part
#
# <(git branch -a | grep -v origin)
## this finds all local branch names and redirects it into the previous command
#
# egrep -v -f /dev/fd/0 STUFF
## this is doing some weird magic that I'm grokking as "take the set difference from whatever was piped in"
#
#
# overall translation: (STUFF TO CONSIDER) | egrep magic <(STUFF TO REMOVE FROM CONSIDERATION) | do cool things with resulting stuff

I did not find the answers here usefull when the remote itself does not exist anymore.当遥控器本身不再存在时,我在这里找不到有用的答案。 I kept seing branches of remotes that did not exist anymore, but did not find a git command to delete them.我一直看到不再存在的遥控器分支,但没有找到删除它们的 git 命令。

The solution for me was to go to the .git\refs\remotes directory and directly delete the files that are not relevant any more.我的解决方案是转到.git\refs\remotes目录并直接删除不再相关的文件。 The file structure is very easy to understand.文件结构非常容易理解。 It is the same structure as what you see with git branch -r .它与您使用git branch -r看到的结构相同。

check for targets检查目标

for target in $(git branch | grep -Eiv "master|develop|branchYouWantToLive"); do echo $target; done

run with for & subcommands使用 for & 子命令运行

for target in $(git branch | grep -Eiv "master|develop|branchYouWantToLive"); do git branch -D $target; done

you can extend other something works about branches.你可以扩展其他关于分支的工作。

In addition to Schleis answer (which works perfectly), this can be integrated into Visual Studio, so pruning local branches when a git repo is open in VS is really simple.除了 Schleis 答案(完美运行)之外,它还可以集成到 Visual Studio 中,因此在 VS 中打开 git repo 时修剪本地分支非常简单。

You can use the External Tools functionality to call sh.exe (git bash) with a specific directory and command.您可以使用外部工具功能通过特定目录和命令调用 sh.exe (git bash)。 This is located in the Tools > External Tools menu option (in VS 2022 17.1.0).它位于工具 > 外部工具菜单选项中(在 VS 2022 17.1.0 中)。 The parameters I use are as follows:我使用的参数如下:

Command : {Path-To-Git-Installation-Location}\bin\sh.exe命令{Path-To-Git-Installation-Location}\bin\sh.exe

Arguments : --cd=$(SolutionDir) -c "git fetch -p ; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d"参数--cd=$(SolutionDir) -c "git fetch -p ; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d"

Initial Directory : $(SolutionDir)初始目录$(SolutionDir)

Screenshot of Git Prune Local Branches Git Prune 本地分支截图

It's worth noting that this will work only when the solution you have open in VS is within a git repo directory.值得注意的是,这仅在您在 VS 中打开的解决方案位于 git repo 目录中时才有效。

Final note - this can be keybound via the Visual Studio key binding user interface in Settings > General > Keyboard and searching for Tools.ExternalCommand[n] where n is the position in the External Command table that you have this external tool positioned at (they can be reordered in the Tools > External Tools dialog).最后说明 - 这可以通过设置 > 常规 > 键盘中的 Visual Studio 键绑定用户界面并搜索Tools.ExternalCommand[n]进行键绑定,其中 n 是外部命令表中您放置此外部工具的位置(它们可以在工具 > 外部工具对话框中重新排序)。 See screenshot below.请参阅下面的屏幕截图。

Keybinding an External Tools Command键绑定外部工具命令

Late to the feast, but you can use the --no-contains option to avoid removing your master branch when using branch --merged晚宴,但您可以使用 --no-contains 选项来避免在使用分支 --merged 时删除您的主分支

git branch --no-contains master --merged master | xargs git branch -d

删除任何与 master 不是最新的分支

git co master && git branch | sed s/\*/\ / | xargs git branch -d 2> /dev/null

I'm pretty sure that git remote prune origin is what you want.我很确定git remote prune origin是你想要的。

You can run it as git remote prune origin --dry-run to see what it would do without making any changes.您可以将其作为git remote prune origin --dry-run ,以查看它在不进行任何更改的情况下做什么。

Using the GUI?使用图形用户界面? Manual procedure, but quick and easy.手动程序,但快速简便。

$ git gui

Select "Branch -> Delete".选择“分支 -> 删除”。 You can select multiple branches with ctrl-click (windows) and remove all of them.您可以使用 ctrl-click (windows) 选择多个分支并删除所有分支。

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

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