在删除远程仓库中的 Git 分支后,如何删除本地 Git 分支?

183

我希望我的本地和远程存储库始终在分支方面保持同步。

在GitHub上进行Pull Request审核后,我会将分支合并并删除(远程)。 如何在本地存储库中获取此信息并让Git也删除我的本地版本分支?


你想删除远程跟踪分支、本地分支还是两者都删除?实际上,你可以编写一个别名(bash 或 git),该别名将处理所有已删除的远程分支,并查找要删除的本地分支副本,一条命令搞定。 - user456814
也许尝试使用以下命令来创建一些内容,git ls-remotegit show-ref - user456814
另外,你可能想要查看git symbolic-refgit update-ref - user456814
3
可能是"[Remove branches no longer on remote]"(https://dev59.com/fmsz5IYBdhLWcg3wsZ8N)的重复问题。 - amaechler
显示剩余2条评论
11个回答

194

快速方式

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

注意:如果你不在 master 分支上,这可能会删除该分支。继续阅读以了解更好的方法。

确保我们保留 master 分支

你可以通过使用 grep 来确保不会删除 master 或任何其他分支。在这种情况下,你需要执行以下命令:

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

所以,如果我们想要保留masterdevelopstaging等分支,我们可以执行以下操作:

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

将其设置为别名

因为它有点长,您可能希望在.zshrc.bashrc中添加一个别名。我的别名叫做gbpurge(表示git分支清理):

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

然后重新载入您的.bashrc.zshrc文件:

. ~/.bashrc

或者

. ~/.zshrc

你可以将这些命令放在别名中,使其成为一个单一的命令。但是,由于branch瓷器而不是管道命令,请注意Git未来版本中任何UI更改可能会破坏它。 - user456814
1
完美!请注意,遵循 Github 工作流程,本地分支 master 将被删除。 - Rubens Mariuzzo
4
如果您想保留多个分支,可以使用单个grep命令,如下所示:grep -Ev '(\*|master|important-branch)' - Andrew Burns
6
如果您想将此内容放入您的 ~/.gitconfig 文件中,可以添加以下代码到 [alias] 部分:gbpurge = !"git branch --merged | grep -Ev '\\*|master|develop|staging' | xargs -n 1 git branch -d" (在 grep 表达式中不需要使用括号)。 - dskrvk
如果你是新手,请小心。添加git别名并在其他存储库中使用它需要额外的注意。并非每个git存储库都将“master | develop | staging”作为主分支。我个人不推荐这种方法。 - Alexar
显示剩余8条评论

108

我使用与GitHub相同的流程,但并没有找到之前的答案令我满意,因为git branch --merged列出了已合并的分支,但在我的情况下,并不是所有这些分支都被远程删除了。所以,这个命令对我有用:

git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d

其中:

  • git fetch --all -p:更新本地分支状态
  • git branch -vv:列出本地分支状态
  • grep ": gone]":过滤已删除的分支
  • awk '{ print $1 }':提取它们的名称
  • xargs -n 1 git branch -d:将名称传递给删除命令

注意:如果您愿意,您可以使用-D而不是-d来强制删除。

例如:

someUsr@someHost:~/repo$ git branch -a
basic-testing
integration-for-tests
* master
origin
playground-for-tests
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

someUsr@someHost:~/repo$ git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d
Fetching origin
Deleted branch integration-for-tests (was fbc609a).
Deleted branch playground-for-tests (was 584b900).

someUsr@someHost:~/repo$ git branch -a
basic-testing
* master
origin
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

参考资料:

http://git-scm.com/book/zh/v2/Git-分支-远程分支


4
我已经自作主张,确保我将始终对主分支进行此操作,因此:git checkout master; git pull origin master; git fetch --all -p; git branch -vv | grep gone | awk '{ print $1 }' | xargs -n 1 git branch -d很棒的脚本和解释,谢谢你 :) - Miguelgraz
1
这是问题的实际答案。谢谢。 - Andrii Gladkyi
3
更好的写法:awk '$3 $4 ~ /:gone]$/ { print $1 }' - Jakub Bochenski
4
除了需要使用“-D”而不是“-d”之外,这是完美的答案! - Cas
1
这个方法完美地运行了,除了在一个特定的 shell 上,我的用户没有被授予访问 xargs 的权限。对于处于同样情况的其他人,你可以使用 while 循环代替 xargs 进行管道传输,像这样:...awk '{ print $1 }' | while read -r line; do git branch -D $line; done - murchu27
显示剩余7条评论

77

尝试运行以下命令:

git pull --prune

它会删除您的本地分支,如果相应的远程分支被删除。

更新:

上面的说法不太正确。

实际上,运行git pull --prune只会删除远程跟踪分支,如下所示:

remotes/origin/fff
remotes/origin/dev
remotes/origin/master

然后,您可以运行git branch -r检查在您的机器上剩下的远程跟踪分支。假设剩下的分支是:

origin/dev
origin/master

这意味着分支 origin/fff 已经被删除了。

因此,在运行 git pull --prune 之后,只需运行:

git branch --merged | grep -vFf <(git branch -r | cut -d'/' -f2-)

就可以找到所有本地分支:

  1. 没有对应的远程分支了;
  2. 可以安全删除。

然后,<上述命令>| xargs git branch -d 可以删除它们。


45
这个答案不太正确。--prune 标志只会删除远程跟踪分支,而不是本地分支。 - user456814
3
同意@Cupcake的观点,这并没有达到我在这里寻求的目标。 - sf89
6
不会给你点赞,但这正是我需要的。之前我删除了本地分支,然后在GitHub上也删除了,但它们仍然以远程方式存在于我的git remote -v命令中。 - Spechal
8
你也可以使用 git fetch --prune 命令,这是我首选的方式。 - e_m0ney
1
又一次从 Stack Overflow 上找到的建议导致了 Git 错误... git pull --prune 导致了 "You asked to pull from the remote '--prune', but did not specify a branch. Because this is not the default configured remote for your current branch, you must specify a branch on the command line." - jww
显示剩余3条评论

24

使用接受的解决方案应该起作用,以避免删除masterdevelopment分支:

git branch --merged | egrep -v "^\*|master|development" | xargs -n 1 git branch -d

18

对于使用PowerShell的人来说,这与上面的答案相当:

git branch -vv | Select-String -Pattern ': gone]' | ForEach-Object{($_ -split "\s+")[1]} | %{ git branch -D $_ }
  1. 筛选所有标记为 gone 的分支
  2. 对找到的每个分支调用 git branch -D(使用 -D 删除未合并分支)。

11
非常简单的解决方案:删除本地仓库并重新克隆远程仓库。这可能看起来不太优雅,但它很简单,而且你无需阅读手册就能完全理解自己在做什么 :-).

3
为什么会有这么多踩?我的意思是,显然对于较大的存储库来说并不高效,但它确实完成了OP要求的任务。还有其他原因不能这样做吗? - 3ocene
9
因为你将会失去所有本地分支、存储的代码片段和未推送的提交记录...这就像使用炸药捕鱼一样。 - sevenseacat
2
当你正在使用的笔记本电脑出现损坏、丢失或被盗时,同样的情况也会发生,因此我不倾向于在本地保存任何重要的东西。对我来说,似乎更好的方法是创建一个分支并将其推送,即使是针对小功能,也可以在不再有用后删除它。 - user4117783

7
如果您已经将分支推送并合并到主分支,则在git bash中执行以下操作:
git branch -d branch_name_to_delete

如果您目前在该分支中,它将把您推回主分支。此时,请使用 pull 命令进行同步。

git pull

1
这种方法相比其他答案有一个优点,即“实际回答了问题的要求 - 即在单数形式下:‘如何让Git同时删除我本地版本的分支?’”。 - SomeoneElse

6

这样对我没有用。您可以在此处查看我的其他答案: https://dev59.com/nmUo5IYBdhLWcg3w7TCT#34969726

但基本上,我现在将以下内容添加到我的~/.gitconfig文件中:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d

2

我只是为了删除合并后的本地分支而这样做:

git branch -d $(git branch --merged)

如果您想删除不存在的跟踪,请执行以下操作:

git pull --prune

1
我写了这个一行命令来列出所有没有对应远程分支的本地分支:
diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -

完成后,使用xargs轻松删除这些本地分支:
diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -|xargs -r git branch -d

这个列表也包括了“master”,它的表现不如预期,要小心。 - Enrico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接