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

时间:2012-10-25 08:31:13

标签: git

使用git remote prune origin我可以删除不在遥控器上的本地分支。

但我还想删除从这些远程分支创建的本地分支(检查它们是否合并是不错的。)

我该怎么做?

32 个答案:

答案 0 :(得分:707)

修剪后,您可以使用git branch -r获取远程分支列表。可以使用git branch -vv检索具有远程跟踪分支的分支列表。因此,使用这两个列表,您可以找到不在遥控器列表中的远程跟踪分支。

这一行应该可以解决问题(需要bashzsh,不适用于标准的Bourne shell):

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

此字符串获取远程分支列表,并通过标准输入将其传递到egrep。并过滤具有远程跟踪分支的分支(使用git branch -vv并过滤那些具有origin的分支),然后获取该输出的第一列,这将是分支名称。最后将所有分支名称传递给delete branch命令。

由于它使用-d选项,因此在运行此命令时,它不会删除尚未合并到您所在分支的分支。

另请注意,您需要首先运行git fetch --prune ,否则git branch -r仍会看到远程分支。

答案 1 :(得分:347)

如果要删除已合并为master的所有本地分支,可以使用以下命令:

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

More info

答案 2 :(得分:136)

git help fetch提供的信息中,有一个小项目:

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

那么,或许,git fetch -p正是您要找的?

编辑:好的,对于那些在事实发生3年之后仍在辩论这个答案的人,这里有更多关于我为什么提出这个答案的信息......

首先,OP表示他们希望“删除那些从远程分支创建的本地分支[远程不再存在]”。这在git中并非明确无误。这是一个例子。

假设我在中央服务器上有一个repo,它有两个分支,名为AB。如果我将该repo克隆到我的本地系统,我的克隆将具有名为origin/Aorigin/B的本地引用(不是实际的分支)。现在让我们说我做了以下事情:

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

这里的相关事实是我出于某种原因选择在我的本地仓库上创建一个分支,其名称与其来源不同,并且我还有一个本地分支,但尚未存在于原始仓库中。

现在假设我删除远程仓库上的AB分支并更新我的本地仓库(某种形式的git fetch),这会导致我的本地引用{{1 }和origin/A消失。现在,我的本地仓库还有三个分支,origin/BAZ。这些都没有在远程仓库上有相应的分支。其中两个是“从......远程分支创建的”,但即使我知道原点上有一个名为C的分支,我也无法知道B是否已创建来自Z,因为它在此过程中被重命名,可能是有充分理由的。因此,实际上,如果没有一些外部过程记录分支起源元数据,或者知道历史记录的人,则无法分辨哪三个分支(如果有的话)OP正在瞄准移除。如果没有B没有为您自动维护的某些外部信息,git就会尽可能接近,并且任何自动尝试OP所要求的方法都会导致删除过多的风险分支,或遗漏了OP本来想要删除的内容。

还有其他场景,例如,如果我在git fetch -p之外创建三个单独的分支来测试三种不同的方法,然后origin/A消失。现在我有三个分支,显然不能全部匹配名称,但它们是从origin/A创建的,因此对OP问题的字面解释需要删除所有三个分支。但是,如果你甚至找到一种可靠的方法来匹配它们,这可能是不可取的......

答案 3 :(得分:95)

这将删除已修剪远程跟踪分支的本地分支。 (确保您在master分支上!)

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

详细信息:

  • git branch -vv显示&#34;已消失&#34;对于本地分支机构,遥控器已被修剪。

    mybranch abc1234 [origin/mybranch: gone] commit comments
    
  • -d会检查它是否已合并(-D会将其删除)

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

答案 4 :(得分:42)

可以将Git配置为在获取时自动删除对已删除远程分支的引用:

git config --global fetch.prune true

之后调用git fetchgit pull时,会自动删除对已删除远程分支的引用。

答案 5 :(得分:24)

有一个简洁的NPM包为你做(并且应该跨平台工作)。

使用以下内容安装:npm install -g git-removed-branches

然后git removed-branches将显示所有陈旧的本地分支,并git removed-branches --prune实际删除它们。

More info here.

答案 6 :(得分:23)

它将列出远程跟踪分支从远程

删除的本地分支
$ git remote prune origin --dry-run

如果您想从本地取消引用这些未被跟踪的本地分支

$ git remote prune origin

答案 7 :(得分:20)

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 reference

的详细输出

Select-String -Pattern ": gone]"仅获取已从远程删除的记录。

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

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

答案 8 :(得分:15)

如果使用Windows和Powershell,您可以使用以下命令删除已合并到当前检出的分支中的所有本地分支:

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

解释

  • 列出当前分支和已合并到其中的分支
  • 过滤掉当前分支
  • 清除每个剩余分支名称的git输出中的任何前导或尾随空格
  • 删除合并的本地分支

值得首先运行git branch --merged首先只是为了确保它只是删除你期望的内容。

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

答案 9 :(得分:7)

我想要一些能够清除跟踪远程分支的所有本地分支的东西,origin,远程分支已被删除(gone)。我不想删除从未设置为跟踪远程分支的本地分支(即:我的本地开发分支)。另外,我想要一个只使用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'

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

答案 10 :(得分:7)

正如@tzacks所提到的...有一个npm软件包对此很方便。只要做:

npx git-removed-branches --prune

(我会发表评论,但声誉不足)

答案 11 :(得分:6)

更短更安全的单线:

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

在运行之前,请务必签出尚未合并的分支。因为您无法删除当前签入的分支。

答案 12 :(得分:4)

不确定如何一次完成所有操作,但git git branch -d <branchname>只有在完全合并时才会删除本地分支。请注意小写d。

git branch -D <branchname>(注意大写字母D)将删除本地分支,无论其合并状态如何。

答案 13 :(得分:4)

这是我的解决方案:

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

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

答案 14 :(得分:3)

您可以使用此命令:

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

Git Clean: Delete Already-Merged Branches包括分解命令

答案 15 :(得分:2)

在@ 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"

有了这个,一个简单的git pruneitgood将清理本地和&amp;合并后不再需要的远程分支。

答案 16 :(得分:2)

这对于使用git 2.21.0的用户而言有效-它删除了合并到HEAD的本地跟踪分支(我以前在其中--set-upstream进行了推送(我使用push.default=upstream是因为它效果最佳)并具有多个远程站点),并且此上游分支已被fetch --prune删除(或者如果git config中的fetch.prune=true则隐式删除):

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

使用--merged-d使其成为非常“安全”的删除。更具侵略性的版本可能会放弃--merged并使用-D

答案 17 :(得分:2)

根据以上答案,我正在使用这种较短的衬纸:

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

答案 18 :(得分:2)

似乎没有一个安全的单行代码,没有太多的边缘案例(例如分支中以“ master”作为其名称的一部分,等等)。最安全的步骤是:

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

答案 19 :(得分:2)

要删除远程分支

$git remote prune origin

要删除已合并的本地分支

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

答案 20 :(得分:1)

我已将接受的答案转换为强大的脚本。你会发现它in my git-extensions repository

$ git-prune --help
Remove old local branches that do not exist in <remote> any more.
With --test, only print which local branches would be deleted.
Usage: git-prune [-t|--test|-f|--force] <remote>

答案 21 :(得分:1)

以下是@ wisbucky对Windows用户的回答改编:

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

我使用了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

使用无参数调用它来查看列表,然后使用“-d”调用它来执行实际删除,或者为任何未完全合并但仍要删除的分支调用“-D”。

答案 22 :(得分:1)

在git bash中尝试此操作,以获取并修剪对已删除分支的引用,然后修剪跟踪已删除分支的本地分支:

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

请记住首先签出一个不会被删除的分支,这样就不会阻止删除分支。

答案 23 :(得分:1)

Schleis&#39;变体对我不起作用(Ubuntu 12.04),所以让我提出我的(清晰而有光泽的)变体:

变体1(我更喜欢这个选项):

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

变式2:

一个。空转:

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

湾删除分支:

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

答案 24 :(得分:1)

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

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

这将删除您在master分支上时已合并到master中的所有本地分支。

git checkout master进行切换。

答案 25 :(得分:0)

当遥控器本身不存在时,我没有找到有用的答案。 我一直在寻找不存在的远程分支,但是没有找到git命令来删除它们。

对我来说,解决方案是转到.git\refs\remotes目录,然后直接删除不再相关的文件。文件结构很容易理解。该结构与您在git branch -r中看到的结构相同。

答案 26 :(得分:0)

检查目标

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

使用for&子命令运行

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

您可以扩展有关分支的其他功能。

答案 27 :(得分:0)

在Powershell中:

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

答案 28 :(得分:0)

我到达此页面,寻求“如何删除不再具有上游分支的本地检出分支”的答案

我也不在乎是否已合并本地分支,因为进入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

答案 29 :(得分:-2)

使用主

删除任何不是最新的分支
git co master && git branch | sed s/\*/\ / | xargs git branch -d 2> /dev/null

答案 30 :(得分:-4)

我非常确定git remote prune origin是你想要的。

您可以将其作为git remote prune origin --dry-run运行,以查看 所做的事情,而无需进行任何更改。

答案 31 :(得分:-17)

使用GUI?手动程序,但又快捷方便。

$ git gui

选择“分支 - &gt;删除”。您可以使用ctrl-click(窗口)选择多个分支并删除所有分支。