删除跟踪分支不再在远程

Mai*_*tel 996 git git-branch

是否有一种简单的方法可以删除远程等效不再存在的所有跟踪分支?

例:

分支机构(本地和远程)

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

在本地,我只有一个主分支.现在我需要处理bug-fix-a,所以我检查它,处理它,并将更改推送到远程.接下来我用bug-fix-b做同样的事情.

分支机构(本地和远程)

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

现在我有本地分支机构master,bug-fix-a,bug-fix-b.Master分支维护者将我的更改合并到master中并删除他已经合并的所有分支.

那么现在的状态是:

分支机构(本地和远程)

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

现在我想调用一些命令删除分支(在本例中为bug-fix-a,bug-fix-b),这些分支不再在远程存储库中表示.

它会像现有的命令git remote prune origin,但更像是git local prune origin.

aub*_*pwd 1126

git remote prune origin 修剪跟踪分支不在遥控器上.

git branch --merged 列出已合并到当前分支的分支.

xargs git branch -d 删除标准输入上列出的分支.

小心删除列出的分支git branch --merged.该列表可能包含master您不想删除的分支或其他分支.

要在删除分支之前给自己编辑列表的机会,可以在一行中执行以下操作:

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

  • 如果我在`develop`那么`git branch --merged`包括`master`!你可能(肯定!)不想删除它.另外我认为它应该是`git branch -d`,其中小写`-d`表示"安全删除",例如只有删除才能合并. (89认同)
  • 删除merged很有用,但与"删除不在远程的分支"不同. (24认同)
  • 合并分支的第一行是我系统上的`*master`.以下命令对我有用:`git branch -d $(git branch --merged | tail -n +2)` (17认同)
  • 似乎提供了一个改进的解决方案[那里](http://stackoverflow.com/a/16906759/490018). (10认同)
  • 只需使用grep排除master:`git branch --merged | grep -v"master">/tmp/merged-branches && vi/tmp/merged-branches && xargs git branch -d </ tmp/merged-branches` (8认同)
  • 不知怎的,对我来说,这也试图删除与我的所有根目录和文件具有相同名称的分支.有什么方法可以排除那些? (2认同)
  • 如果这可以帮助的话,这是我最喜欢的没有中间文件的单行:`git Branch --merged | egrep -v "(^\*|master|开发)" | xargs git 分支 -d` (2认同)
  • @thom_nic 我不确定删除本地主分支有什么大不了的。人们通常使用的工作流程是为他们处理的每个任务命名分支。`master` 通常不被使用。好吧,ofc 必须以远程主分支为基础进行变基,但这将是一个“上游/主”*(或者任何你所说的上游远程分支)*。我什至有一个使用“upstream/master”的 git 别名“git newbranch”。无需使用多余的本地主分支。举个例子,我所从事的项目中的主分支已经很长时间没有更新了。您使用不同的工作流程吗? (2认同)
  • 对我来说最好的办法是。`git 远程修剪原点 | gitbranch -d $(gitbranch --merged | grep -v 'develop' | grep -v 'master') ` 效果很好 (2认同)

jas*_*man 497

命令之后

git fetch -p
Run Code Online (Sandbox Code Playgroud)

运行时删除远程引用

git branch -vv
Run Code Online (Sandbox Code Playgroud)

它将显示为"已离开"作为远程状态.例如,

$ 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
Run Code Online (Sandbox Code Playgroud)

因此,您可以编写一个简单的脚本来删除已经转移的本地分支:

git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
Run Code Online (Sandbox Code Playgroud)

  • @dlsso如果最后一个提交消息包含字符串":gone",那么它也将被删除.您可以通过额外的awk/gawk去除提交消息来使其更加健壮,但代价是简单.`git branch -vv | gawk'{print $ 1,$ 4}'| grep'走了''| gawk'{print $ 1}'` (10认同)
  • @KrzysztofWende - 不在Solaris和一些BSD和一些OS X :) (8认同)
  • 看起来这也将删除在最后一次提交消息中"已消失"的任何分支. (4认同)
  • @ahmedbhs因为命令使用单引号"你需要使用双引号"来包围整个命令.另外,作为shell命令的git别名(比如这一个)在开头需要!这对我有用:`test =" !git fetch -p &&用于\`git branch -vv |中的分支 grep':gone]'| awk'{print $ 1}'\`; 做git branch -D $ branch; 做"` (3认同)
  • `git Branch -D` 接受多个分支,因此不需要循环。格式变量还支持剥离部分。因此,这可以简化为 `gitbranch -D $(git for-each-ref --format '%(refname:strip=2) %(upstream:track)' refs/heads | awk '$2 == "[gone ]" {打印 $1}')` (3认同)
  • 在回复我之前的评论(问题)时,当前分支将\*作为第一个字段.如果它恰好也在"消失"分支列表中,那么$ 1将被分配\*并且将被解释为具有awk吐出文件和文件夹名称的文件规范.我删除了grep表达式并让awk完成所有过滤:`awk'/:gone]/{if($ 1!="*")print $ 1}'`.这现在按预期工作. (2认同)
  • 我的版本:```git branch -vv | grep ': 不见了]' | awk '{print $1}' | xargs -n1 echo git branch -d``` (2认同)
  • 正如@fiorentinoing 所提到的,我宁愿使用 `-d` 而不是 `-D`,以保留尚未合并的分支,这些分支可能仍然包含一些有价值的(尽管可能是实验性的)代码。我将用我自己的方式添加到这里的自行车棚:`git branch -v|grep消失|awk '{print $1}'| xargs git branch -d` (2认同)
  • @jason.rickman,更强大 - 更高效 - 是直接在 `awk` 中过滤:`git Branch -vv | awk '$4 = "gone]" {print $1}'`. (2认同)

dls*_*sso 273

这些答案中的大多数实际上并未回答原始问题.我做了一堆挖掘,是我找到的最干净的解决方案.这是一个稍微更全面的答案:

  1. 查看您的默认分支.平时git checkout master
  2. git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

说明:

通过修剪您的跟踪分支然后删除显示它们"已消失"的本地分支来工作git branch -vv.

笔记:

如果您的语言设置为英语以外的其他语言,则需要更改gone为相应的单词.不会触及仅限本地的分支.已在远程删除但未合并的分支将显示通知但不会在本地删除.如果你想删除那些以及更改-d-D.

  • 当您在应该删除的分支上时,这很危险 - 在这种情况下,第一列是 '\*',然后将其传递给 xargs。为了改进这一点,在将输出传递给 awk 之前添加剥离 '*' 字符: sed -e 's/^\*//' (5认同)
  • 应该在git branch之前添加LANG = en_US来强制执行英语:git fetch --prune && LANG = en_US git branch -vv | awk'/:gone]/{print $ 1}'| xargs git branch -d (4认同)
  • 我会在命令的开头添加`git checkout master && ...`. (3认同)
  • 小心!有一个极端的情况会导致删除所有本地分支:如果您当前正在远程删除的分支,则git branch -vv的输出将以星号开头,最终将导致执行` git branch -d *`。这是一个补丁版本,将忽略带星号的行:`git branch -vv | grep':走了]'| grep -v“ \ *” | awk'{print $ 1; }'| xargs -r git branch -d` (3认同)
  • 对于法国的操作系统,必须通过视而不见来更改 (2认同)
  • @dlsso 这些说明适用于大多数人,但不适用于所有人(请参阅上面的评论)。说人们应该从意外删除的分支中学习(他们可能不容易知道如何恢复)是一种光顾,当您可以使说明更安全时。你,你自己在上面写道“那个确切的建议是不安全的”。我仍然认为安全比总是工作更重要。人们最好从“不工作”中学习,而不是从已删除的分支中学习。 (2认同)
  • @meeee指令*do*适合所有人,其余的只是哲学上的差异.对于那些忽视指令的人,我选择优先考虑安全性的优先级,因为我认为堆栈溢出是一个学习的地方,而不是发布产品的地方.而且我不了解你,但我宁愿学会遵循指令删除一些"git checkout"而不是"rm -rf"系统目录.:) (2认同)
  • 感谢`LANG = zh_CN`,`LC_ALL = C`会更好地工作。 (2认同)
  • @disso 您的默认分支也可以在远程删除。我不会依赖那个。一旦分支列表中出现星号,您的所有本地分支都将被删除。 (2认同)

And*_*cer 170

我通常不会回答已有16个答案的问题,但所有其他答案都是错误的,正确的答案是如此简单.问题是,"是否有一种简单的方法可以删除远程等效不再存在的所有跟踪分支?"

如果"简单"意味着不脆弱,没有危险,并且不依赖于并非所有读者都会拥有的工具,那么正确答案是:不.

有些答案很简单,但他们并没有按照要求做.其他人做了所要求的,但并不简单:所有人都依赖于通过文本操作命令或脚本语言解析Git输出,这些语言可能不会出现在每个系统上.最重要的是,大多数建议使用瓷器命令,其输出不是设计为由脚本解析("瓷器"是指用于人工操作的命令;脚本应使用较低级别的"管道"命令).

进一步阅读:


如果你想安全地这样做,对于问题中的用例(垃圾收集跟踪分支已经在服务器上删除但仍然作为本地分支存在)和仅使用高级Git命令,你必须

  • git fetch --prune(或者git fetch -p,这是一个别名,或者git prune remote origin在没有提取的情况下做同样的事情,并且可能不是你想要的大部分时间).
  • 请注意报告为已删除的任何远程分支.或者,稍后查找它们git branch -v(任何孤立的跟踪分支将被标记为"[已消失]").
  • git branch -d [branch_name] 在每个孤立的跟踪分支上

如果你想编写一个解决方案的脚本,那么for-each-ref就是你的起点,就像马克·朗格尔在这里的答案另一个问题的答案一样,但是我没有办法在没有编写shell脚本循环或使用xargs之类的情况下利用它.


背景说明

要了解正在发生的事情,您需要意识到,在跟踪分支的情况下,您没有一个分支,而是三个分支.(并且回想一下"分支"仅仅意味着指向提交的指针.)

给定跟踪分支feature/X,远程存储库(服务器)将具有此分支并调用它feature/X.你的本地存储库有一个分支remotes/origin/feature/X,意思是"这就是遥控器告诉我它的功能/ X分支是什么,上次我们谈过",最后,本地存储库有一个分支feature/X指向你的最新提交,并配置为"轨道" remotes/origin/feature/X,意味着你可以拉动并推动它们保持对齐.

在某些时候,有人删除feature/X了遥控器上的.从那一刻起,你就离开了你的本地feature/X(你可能不再需要了,因为功能X上的工作可能已经完成了),而你remotes/origin/feature/X的当然无用,因为它的唯一目的是记住服务器分支的状态.

并且Git会让你自动清理冗余remotes/origin/feature/X- 这就是做什么git fetch --prune- 但由于某种原因,它不会让你自动删除你自己的feature/X...即使你feature/X仍然包含孤立的跟踪信息,所以它有信息识别已完全合并的以前跟踪分支.(毕竟,它可以为提供让您自己手动操作的信息.)

  • 我认为使用 Git 对于“有没有一种简单的方法......”这个问题的答案几乎总是“没有”。 (16认同)
  • 这实际上只回答了问题“如何找到消失的分支”的简单部分(以及与 jason.rickman 在 2015 年发布的命令相同的命令),然后告诉您手动删除所有分支,这正是 OP不想做。 (6认同)
  • @user2864740 一些读者可能认为编写一个小的 bash 脚本符合他们对“简单”的定义,这是一个完全站得住脚的立场,但我在第 2 段中对“简单”给出了自己的解释,其余的答案是一致的用它。为了捍卫我公认的限制性解释,并非所有 Git 用户都有 `xargs` 或 bash,他们可能不是在这里寻找微编码挑战,而是一个快速的答案,他们可以安全地应用,而不会分散他们的注意力他们的真正目标。 (4认同)
  • @Voo这就是答案的重点:不是告诉你怎么做(这只是一个奖励),而是告诉你答案是没有简单的方法来做到这一点。这是对提出的问题的正确答案。 (3认同)
  • 这是一个更安全的答案。此外,如果您使用“压缩并合并”工作流,它将与选定的答案不同,这将起作用。 (2认同)
  • @Andrew 如果您有一个完全符合您要求的瓷器命令,则似乎不太可能使用管道命令来可靠地获得相同的输出。我确实问过这个问题,并在不到一个小时内得到了 [答案](/sf/ask/3745251401/?noredirect=1#comment93879166_53503591)。可能应该按照这些方式发布答案(#17?)。 (2认同)

kar*_*gen 51

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

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
Run Code Online (Sandbox Code Playgroud)

确保我们保持主人

您可以master通过grep在第一个分支之后添加另一个分支来确保不会删除该分支或任何其他分支.在那种情况下你会去:

git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d
Run Code Online (Sandbox Code Playgroud)

因此,如果我们想继续保持master,developstaging举例来说,我们会去:

git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d
Run Code Online (Sandbox Code Playgroud)

把它作为别名

由于它有点长,您可能想要为您的.zshrc或添加别名.bashrc.我被称为gbpurge(for git branches purge):

alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'
Run Code Online (Sandbox Code Playgroud)

然后重新加载你的.bashrc.zshrc:

. ~/.bashrc
Run Code Online (Sandbox Code Playgroud)

要么

. ~/.zshrc
Run Code Online (Sandbox Code Playgroud)

  • 有用,但与"删除不在远程的分支"不同 (6认同)

Mai*_*tel 47

似乎解决方案在这里 - /sf/answers/75052491/

总之,git remote prune是否有魔力

  • 据我所知并尝试过,这并没有删除本地分支机构.它只从远程/*中删除. (93认同)
  • 具有讽刺意味的是因为他是第一个提出这个问题的人! (35认同)
  • 不解决原始问题. (21认同)
  • 删除本地(合并分支):"git branch -D \`git branch --merged | grep -v master \`"说明:"git branch --merged"输出已经合并的本地分支.由于'master'属于这些分支,我们必须通过反grep过滤掉它.警告 - 小心使用:) (12认同)
  • 如果您不确定,请添加--dry-run选项,并将转储要修剪的分支列表. (6认同)

chr*_*389 32

Windows解决方案

对于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 $_}

git checkout master 切换到主分支

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

git branch -vv得到所有分支的详细输出(git引用)

Select-String -Pattern ": gone]" 只获取从远程删除它们的记录.

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

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

  • 谢谢你,虽然我必须在`.toString()`之后添加一个`.Trim()`,以便在分支名称之前删除两个空格. (3认同)
  • 感谢这个命令。我不得不将 `git branch -d` 更改为 `git branch -D`,否则我会收到分支未完全合并的错误。 (2认同)
  • @markieo 你可能已经知道这一点,但对于其他人来说 - `git Branch -D` 是**破坏性的**,并且会删除您尚未推送的本地工作。`-d` 总是安全的,只要小心使用 `-D` 即可。 (2认同)

cs0*_*s01 31

删除已合并为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 branch -D`命令更安全 (3认同)
  • 或者使用小写的“gitbranch-d”,它应该发出有关未推送分支的警告。 (2认同)

Pra*_*tti 30

虽然上面的答案涵盖了如何手动修剪分支,但这个答案增加了自动化来解决这个问题。git现在有一个新的设置来修剪不再在每个获取操作的远程上的陈旧分支。这很棒,因为我们不再需要remote prune每次删除分支时都手动调用(git pull也调用git fetch)。

为每次提取启用修剪行为

要在全局配置中启用此功能:

git config --global fetch.prune true
Run Code Online (Sandbox Code Playgroud)

让事情自动发生意味着您可能会忘记在新机器上添加此设置。它就是有效的。

为特定远程上的每次提取启用修剪行为

git config --global remote.<name>.prune true
Run Code Online (Sandbox Code Playgroud)

本地自动修剪

我们也可以在不使用该标志的情况下应用相同的命令进行本地修剪--global

.gitconfig

上述命令适用于全局和局部,.gitconfig如下所示:

...
[fetch]
    prune = true
Run Code Online (Sandbox Code Playgroud)

我建议将其添加到 ansible 配置或您的 dotfiles 存储库 ( .gitconfig) 中,以便将来自动进行设置。

配置设置在每次获取时调用以下命令:

git remote prune <remote name>
Run Code Online (Sandbox Code Playgroud)

概括

要修剪引用作为正常工作流程的一部分,而不需要记住运行它,请在配置中fetch.prune全局或按远程设置。remote.<name>.prune请参阅git-config

  • 似乎对我不起作用。执行全局设置(也在我的 .gitconfig 中),合并 github 上的分支,然后是 `git fetch` + `git pull`。该分支机构仍然存在于我的本地。 (2认同)

Sve*_*ens 29

你可以这样做:

git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d
Run Code Online (Sandbox Code Playgroud)

PS:正如Sam H.

首先执行这个:

git remote prune origin
Run Code Online (Sandbox Code Playgroud)

  • 你不需要先运行“git Remote prune origin”吗? (2认同)
  • 如果你想强制删除,还可以传递`xargs gitbranch -D`(大写D) (2认同)

nor*_*raj 26

特尔;博士:

删除所有不在远程的本地分支

git fetch -p && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D
Run Code Online (Sandbox Code Playgroud)

删除所有不在远程且已完全合并且未如之前许多答案中所述使用的本地分支

git fetch -p && git branch --merged | grep -v '*' | grep -v 'master' | xargs git branch -d
Run Code Online (Sandbox Code Playgroud)

解释

  • git fetch -p 将修剪远程不再存在的所有分支
  • git branch -vv will print local branches and pruned branch will be tagged with gone
  • grep ': gone]' selects only branch that are gone
  • awk '{print $1}' filter the output to display only the name of the branches
  • xargs git branch -D will loop over all lines (branches) and force remove this branch

Why git branch -D and not git branch -d else you will have for branches that are not fully merged.

error: The branch 'xxx' is not fully merged.
Run Code Online (Sandbox Code Playgroud)


Pat*_*irk 25

大多数其他解决方案中"消失"的模式匹配对我来说有点吓人.为了更安全,它使用--format标志来提取每个分支的上游跟踪状态.

我需要一个Windows友好版本,所以这将使用Powershell删除列为"已消失"的所有分支:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }
Run Code Online (Sandbox Code Playgroud)

第一行列出了上游分支"已消失"的本地分支的名称.下一行删除空白行(对于未"消失"的分支输出),然后将分支名称传递给命令以删除分支.

  • `--format`选项似乎相当新; 我需要将git从2.10.something升级到2.16.3才能获得它.这是我对Linux-ish系统的修改:`git branch --list --format"%(if:equals = [gone])%(upstream:track)%(then)%(refname)%(end)"| sed's,^ refs/heads/,,'| grep.| xargs git branch -D` (5认同)
  • 对于 Windows 来说,这是一个很好的解决方案。我这样使用它是因为它更具可读性`gitbranch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end )" | 其中 { $_ -ne "" } | foreach { gitbranch -d $_ }` 使用 `-d` 而不是 `-D` 可能也是个好主意。对于不再位于远程的分支,不需要强制删除。 (3认同)
  • 到目前为止,这是最好的解决方案.一个建议是使用`refname:short`.然后你可以删除行'%{$ _ -replace'^ refs/heads /',''}` (2认同)

Him*_*ura 21

另一个答案,因为没有一个解决方案适合我对优雅和跨平台的需求:

删除不在远程的本地分支的命令:

for b in $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads); do git branch -d $b; done
Run Code Online (Sandbox Code Playgroud)

将它与 gitconfig 集成,以便它可以运行 git branch-prune

重击

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format='\''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'\'' refs/heads); do git branch -d $b; done'
Run Code Online (Sandbox Code Playgroud)

电源外壳

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format=''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'' refs/heads); do git branch -d $b; done'
Run Code Online (Sandbox Code Playgroud)

(需要帮助寻找 PowerShell 和 bash 的通用命令)

为什么这个答案是最好的?

  • 提供完整的解决方案:git branch-prune向您的 git添加命令
  • 从 Windows PowerShell 工作正常
  • 核心思想是@jason.rickman防弹方法使用git for-each-ref
  • 解析和过滤是在--filter不需要外部依赖的情况下完成的

解释:

  • 将新别名添加到您的~\.gitconfig. 执行此操作后,您可以简单地执行git branch-prune
  • 在这个别名中:
    • 使用--prune标志获取分支,该标志“修剪远程跟踪分支不再位于远程”
    • 使用git for-each-refand --filter, 获取分支列表[gone](无远程)
    • 循环遍历此列表并安全删除分支


Asa*_*af 18

你可以使用这个:

git fetch --prune
Run Code Online (Sandbox Code Playgroud)

然后

git branch -vv | egrep -v "([origin/[a-zA-Z0-9/_-]+])" | awk "{print $1}" | xargs git branch -D
Run Code Online (Sandbox Code Playgroud)

它删除所有未链接到远程的本地分支

我亲自添加了一个别名来为我做这件事

alias gbs='git fetch --prune; git branch -vv | egrep -v "(\[origin\/[a-zA-Z0-9/_-]+\])" | awk "{print \$1}" | xargs git branch -D'
Run Code Online (Sandbox Code Playgroud)


cki*_*ey3 14

git fetch -p
Run Code Online (Sandbox Code Playgroud)

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

  • 这将删除远程引用,但不删除本地分支本身.虽然这是一个有用的命令,但我认为这并不能解决OP的问题. (56认同)
  • 什么?这会删除我的本地分支。 (3认同)
  • @AlexHall 远程仓库有一个分支`X`;你`git checkout X`; 现在您的存储库有一个(本地)跟踪分支“X”和一个远程分支“origin/X”;远程仓库删除了‘X’;你`git fetch-p`; 在您的本地存储库中,不仅“origin/X”而且“X”都已被删除。这是你说的吗? (2认同)

Fra*_*ois 14

可能对某些简单的一行有用,可以清除除master和develop之外的所有本地分支

git branch | grep -v "master" | grep -v "develop" | xargs git branch -D
Run Code Online (Sandbox Code Playgroud)

  • 但这并不能回答上面的问题。即使远程仍然存在,这也会删除分支。 (2认同)

kar*_*bal 14

因为有些答案不\xe2\x80\x99t防止意外删除

\n

git fetch -p && LANG=c git branch -vv | awk '/: gone]/&&!/^\\*/{print $1}' | xargs git branch -d

\n

*过滤掉第一列中的分支很重要。

\n


Mar*_*air 13

我认为没有内置命令可以执行此操作,但执行以下操作是安全的:

git checkout master
git branch -d bug-fix-a
Run Code Online (Sandbox Code Playgroud)

当你使用时-d,git将拒绝删除分支,除非它完全合并到HEAD其上游远程跟踪分支.因此,您可以始终循环输出git for-each-ref并尝试删除每个分支.这种方法的问题在于我怀疑你可能不想bug-fix-d因为origin/bug-fix-d包含其历史而被删除.相反,您可以创建类似以下内容的脚本:

#!/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
Run Code Online (Sandbox Code Playgroud)

警告:我没有测试过这个脚本 - 只能小心使用...


pab*_*a98 13

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

git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d
Run Code Online (Sandbox Code Playgroud)

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

git remote prune origin
Run Code Online (Sandbox Code Playgroud)


bxm*_*bxm 10

还有另一个答案,大量来自/sf/answers/3388808811/(我喜欢它,因为它似乎消除gone]git branch输出中匹配位置的任何歧义)但添加了*nix弯曲:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" \
  | sed 's,^refs/heads/,,;/^$/d' \
  | xargs git branch -D
Run Code Online (Sandbox Code Playgroud)

我把它包含git-gone在我的路径上的脚本中:

#!/usr/bin/env bash

action() {
  ${DELETE} && xargs git branch -D || cat
}

get_gone() {
  git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" \
    | sed 's,^refs/heads/,,;/^$/d'

}

main() {
  DELETE=false
  while [ $# -gt 0 ] ; do
    case "${1}" in
      (-[dD] | --delete) DELETE=true ;;
    esac
    shift
  done
  get_gone | action
}

main "${@}"
Run Code Online (Sandbox Code Playgroud)

NB - --format选项似乎相当新; 我需要将git从2.10.something升级到2.16.3才能获得它.


Pxt*_*xtl 9

我发现基于 Powershell 的解决方案比这里的许多实现更清晰。

# prune deleted remoted branches
git fetch -p

# get all branches and their corresponding remote status
# deleted remotes will be marked [gone]
git branch -v |
  #find ones marked [gone], capture branchName
  select-string -Pattern '^  (?<branchName>\S+)\s+\w+ \[gone\]' | 
  foreach-object{ 
     #delete the captured branchname.
     git branch -D $_.Matches[0].Groups['branchName']
  }
Run Code Online (Sandbox Code Playgroud)


小智 7

grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d
Run Code Online (Sandbox Code Playgroud)

上面的命令可用于获取在远程中合并和删除的分支,并删除在远程中不再可用的本地分支

  • 如果您的任何分支名称碰巧在其中的任何位置包含子字符串“gone”(例如“usingonefunction”),则很危险。 (2认同)

Joo*_*oer 6

根据上面的信息,这对我有用:

git br -d `git br -vv | grep ': gone] ' | awk '{print $1}' | xargs`
Run Code Online (Sandbox Code Playgroud)

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

  • "git branch -D git branch -vv | grep':gone]'| awk'{print $ 1}'| xargs`"这对我有用. (3认同)

Kar*_*bur 5

这些都不适合我。我想要一种能够清除所有正在跟踪远程分支的本地分支的方法,该分支位于origin已删除(gone)的远程分支。我不想删除从未设置为跟踪远程分支的本地分支(即:我的本地dev分支)。我还想要一个仅使用git或其他简单的CLI工具的简单的一线工具,而不是编写自定义脚本。我最终使用了grepawk做这个简单的命令。

最终这就是我的结果~/.gitconfig

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

这是一个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'
Run Code Online (Sandbox Code Playgroud)

注意:在config命令中,我使用-d选项git branch而不是-D,就像在实际配置中一样。我使用它-D是因为我不想听到Git关于合并分支的抱怨。您可能还需要此功能。如果是这样,只需在config命令的末尾使用-D而不是即可-d


gsn*_*ers 5

从大量图纸数量 其他 的答案在这里,我已经结束了与以下(GIT 2.13及以上的只有,我相信),它应该在任何运行类UNIX外壳:

git for-each-ref --shell --format='ref=%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)' refs/heads | while read entry; do eval "$entry"; [ ! -z "$ref" ] && git update-ref -d "$ref" && echo "deleted $ref"; done
Run Code Online (Sandbox Code Playgroud)

这特别使用了for-each-ref而不是branch(因为它branch是为人类可读的输出而设计的“瓷器”命令,而不是机器处理)并使用其--shell参数来获得正确转义的输出(这使我们不必担心引用名称中的任何字符)。


归档时间:

查看次数:

377722 次

最近记录:

6 年 前