如何修剪本地跟踪分支,这些分支在远程不存在了?

1322

使用git remote prune origin可以删除本地不再追踪的远程分支。

但是我也想删除从这些远程分支创建的本地分支(检查它们是否未合并会很好)。

我应该怎么做?


12
可能是「删除不在远程的本地分支」的重复问题。 - kolen
6
一句话介绍:跨平台的命令行工具,不会让人觉得像猫睡在你的键盘上一样混乱。要使用此工具,请先安装_node.js_。使用npx git-removed-branches(干运行) 或 npx git-removed-branches --prune(真实运行)。详细信息请参见以下答案 - Cristian Diaconescu
我通常认为这些事情应该是有意识地完成,而不是自动化的,否则你会面临删除你不想删除的东西的风险。因此,我会坚持使用 git branch -d localBranchName 和 git push origin --delete remoteBranchName。 - Epirocks
3
对于使用IntelliJ的用户,以下插件正好满足您的需求:https://plugins.jetbrains.com/plugin/10059-git-branch-cleaner - Daniel
40个回答

20
我希望有一个可以清除所有正在跟踪已删除(gone)的远程分支在 origin 上的本地分支的命令,而不删除从未设置跟踪远程分支(例如:我的本地开发分支)的本地分支。此外,我想要一个简单的一行命令,只使用 git 或其他简单的 CLI 工具,而不编写自定义脚本。最终,我使用了一点 grepawk 来创建这个简单的命令,然后将其添加为别名到我的 ~/.gitconfig 文件中。
[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

以下是一个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'

注意: 使用git branch命令时的-D标志可能非常危险。因此,在上面的配置命令中,我使用git branch-d选项而不是-D; 我在实际配置中使用-D。我使用-D,因为我不想听到 Git 抱怨未合并的分支,我只想让它们消失。您可能也需要此功能。如果是这样,请在该配置命令的末尾使用-D代替-d


19

更短且更安全的一行代码:

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

在运行之前,请确保切换到尚未合并的分支,因为您无法删除当前检出的分支。


3
这是否也会删除你的“主控”? - dcsan
2
如果您当前已经签入主分支,则不需要,否则是的。 - FelikZ
2
要跳过主分支,您可以使用管道符号并选择反向grep,如下所示 - git branch -d $(git branch --merged | cut -c 3- | grep -v master) - mozillalives
这是不安全的,未来的某个人将无意中删除他们的主分支。 - jasonseminara
2
@jasonseminara #dcsan 我已经更新了代码片段,所以它会跳过主分支。 #mozillalives 谢谢。 - FelikZ
将来的某个人会无意中删除他们的“开发”分支。 - Jim.B

13

这是我的解决方案:

git fetch -p
git branch -vv | grep ": gone" | awk '{print $1}' | xargs git branch -d
  • -p 用于删除在远程不存在的任何远程跟踪引用。因此,第一步将删除对远程分支的引用。

  • -vv 用于显示每个head的sha1和提交主题行,以及与上游分支(如果有)的关系。第二步将获取所有本地分支,并使用grep命令过滤已删除的分支。


甚至更小(如另一条评论所述)git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d - mrroboaat
我必须将最后一个 -d 改为 -D,否则你的第二行代码会在每个分支上给我输出以下内容: error: The branch 'your-branch' is not fully merged. If you are sure you want to delete it, run 'git branch -D your-branch'. - NateH06

12

似乎没有一个安全的一行命令可以解决这个问题,因为有太多的特殊情况(例如分支名称中包含“master”等)。最安全的方法是按照以下步骤进行操作:

  1. git branch -vv | grep 'gone]' > stale_branches.txt
  2. 查看文件并删除您想保留的分支的行(例如主分支!);您不需要编辑任何行的内容
  3. awk '{print $1}' stale_branches.txt | xargs git branch -d

8
这个命令和下面的脚本在Linux和Windows的Git Bash(MinGW)中都可以使用。
最好使用git的内部命令,以免意外匹配或删除不想要删除的分支。有许多内部"原子"可以与git for-each-ref的格式选项一起使用,以输出所需的信息。这样我们就不必依赖于管道传输到awkgrep来检查可能包含不必要信息的输出的正则表达式。
下面的命令仅使用git for-each-ref的内部低级命令来列出孤立的本地分支。 一旦你找到了它们,就可以将其传输到git branch -D。另外,别忘了先修剪和获取你的远程引用,否则它将找不到匹配项:
git fetch -p
git for-each-ref --format '%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' 'refs/heads/**' | xargs -r git branch -D

这里是详细说明:
- git fetch -p - 清除移除的引用并从远程获取新的引用。 - git for-each-ref --format - 使用特定格式列出所有引用。 - %(if:equals=[gone])%(upstream:track) - 仅输出如果上游追踪分支是"[gone]"。 - %(then)%(refname:short)%(end) - 输出分支名称(当跟踪被删除时)。 - refs/heads/** - 限制为头引用(以提高效率)。 - | xargs -r git branch -D - 将输出作为删除的参数传递。 -r 表示忽略空输入。
单独使用此解决方案会很长,难以记忆和键入。幸运的是,将自定义命令添加到Git很容易。下面是一个脚本,它使用了上面的相同命令,但允许用户使用 --dry-run 选项查看将选择哪些分支。
我将文件命名为 git-prune-local 并将其放置在我的 PATH 中包含的文件夹中。还需要执行权限(chmod 755 git-prune-local)。
Git会自动查找可执行文件,如 git-[command]。因此,您只需要键入 git prune-local 即可删除正确的分支。
#!/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"

8

删除远程分支:

$git remote prune origin

删除已经合并的本地分支:

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

可以用。谢谢。 - AndroidRuntimeException
9
对我来说,(git branch --merged)也会返回'master'。以及其他尚未被删除的远程分支。 (注:建议将上下文提供给读者以获得更好的理解) - Tom G
45
这使我的主分支被删除了。 - Greg
1
可能更好的方法是: $git branch -D $(git branch --merged | egrep -v '^\*|^\s+master$'),这样就可以过滤掉主分支和当前分支了。 - Skeeve
这里能用 git branch --no-contains <main_or_master> --merged 吗? - bluesmonk

6
Powershell中:
git branch -D (git branch --merged |% { $_.trim() } )

5

根据以上答案,我正在使用这个更短的一行代码:

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

此外,如果您已经剪枝并且有本地的悬挂分支,则此操作将清理它们:
git branch -vv | awk '/^ .*gone/{print $1}' | xargs -r git branch -d

1
如果您的分支名称中存在“/”,则无法正常工作。 - theicfire

5

在支持cut -w的OS X系统上

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

说明

删除以下分支
git branch -d ...

显示已删除的分支

$ 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

保留分支名称

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

5
晚来的宾客也不迟,当你使用分支--merged时,你可以使用--no-contains选项避免删除你的主分支。
git branch --no-contains master --merged master | xargs git branch -d

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