git 列出所有没有遥控器的本地分支

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15661853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 15:51:04  来源:igfitidea点击:

List all local branches without a remote

gitgit-remote

提问by JC Denton

Problem: I want a way of deleting all the local branches I have that do not have a remote. It's easy enough to pipe the names of the branches into a git branch -D {branch_name}, but how do I get that list in the first place?

问题:我想要一种删除所有没有遥控器的本地分支的方法。将分支的名称通过管道传输到 a 中很容易git branch -D {branch_name},但是首先我如何获得该列表?

For example:

例如:

I create a new branch without a remote:

我创建了一个没有遥控器的新分支:

$ git co -b no_upstream

I list all my branches, and there's only one with a remote

我列出了我所有的分支,只有一个有遥控器

$ git branch -a
master
* no_upstream
remotes/origin/HEAD -> origin/master
remotes/origin/master

What command can I run to get no_upstreamas an answer?

我可以运行什么命令来获得no_upstream答案?

I can run git rev-parse --abbrev-ref --symbolic-full-name @{u}and that will show that it has no remote:

我可以运行git rev-parse --abbrev-ref --symbolic-full-name @{u},这将表明它没有遥控器:

$ git rev-parse --abbrev-ref --symbolic-full-name @{u}
error: No upstream configured for branch 'no_upstream'
error: No upstream configured for branch 'no_upstream'
fatal: ambiguous argument '@{u}': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

But as this is an error, it won't let me use it or pipe it to other commands. I'm intending to use this as either a shell script alias'd to git-delete-unbranchedor maybe make a super simple Gem like git-branch-delete-orphans

但由于这是一个错误,它不会让我使用它或通过管道将它传递给其他命令。我打算将它用作 shell 脚本的别名,git-delete-unbranched或者制作一个超级简单的 Gem,例如git-branch-delete-orphans

回答by Jeremy Baker

I recently discovered git branch -vvwhich is the "very verbose" version of the git branchcommand.

我最近发现git branch -vv这是命令的“非常冗长”版本git branch

It outputs the branches along with the remote branches if they exist, in the following format:

它以以下格式输出分支以及远程分支(如果存在):

  25-timeout-error-with-many-targets    206a5fa WIP: batch insert
  31-target-suggestions                 f5bdce6 [origin/31-target-suggestions] Create target suggestion for team and list on save
* 54-feedback-link                      b98e97c [origin/54-feedback-link] WIP: Feedback link in mail
  65-digest-double-publish              2de4150 WIP: publishing-state

Once you have this nicely formatted output, it's as easy as piping it through cutand awkto get your list:

一旦你有了这个格式很好的输出,就像通过管道传递它cutawk获取你的列表一样简单:

git branch -vv | cut -c 3- | awk ' !~/\[/ { print  }'

Results in the following output:

结果如下:

25-timeout-error-with-many-targets
65-digest-double-publish

The cutportion just normalizes the data by removing the first two characters (including *) from the output before passing it to awk.

cut部分只是通过在将数据*传递给 之前从输出中删除前两个字符(包括)来规范化数据awk

The awkportion prints the first column if there is no square bracket in the third column.

awk如果第三列中没有方括号,该部分将打印第一列。

Bonus: Create an alias

奖励:创建别名

Make it easy to run by creating an alias in your global .gitconfigfile (or wherever):

通过在全局.gitconfig文件(或任何地方)中创建别名,使其易于运行:

[alias]
  local-branches = !git branch -vv | cut -c 3- | awk ' !~/\[/ { print  }'

Important: The backslash needs to be escaped in the alias or else you will have an invalid gitconfig file.

重要提示:反斜杠需要在别名中转义,否则您将拥有无效的 gitconfig 文件。

Bonus: Remote Filtering

奖励:远程过滤

If for some reason you have multiple tracking remotes for different branches, it's easy enough to specify which remote you want to check against. Just append the remote name to the awk pattern. In my case, it's originso I can do this:

如果出于某种原因,您有多个跟踪不同分支的遥控器,则很容易指定要检查的遥控器。只需将远程名称附加到 awk 模式。就我而言,origin我可以这样做:

git branch -vv | cut -c 3- | awk ' !~/\[origin/ { print  }'

回答by VonC

git branch(without any options) lists only local branches, but you don't know if they are tracking a remote branch or not.

git branch(没有任何选项)仅列出本地分支,但您不知道它们是否正在跟踪远程分支。

Usually those local branches should be deleted once merged into master(as seen in this issue of git-sweep):

通常,这些本地分支应在合并后删除master(如本期 git-sweep 所示):

git branch --merged master | grep -v master | xargs git branch -d

This isn't as complete as you want, but it is a start.

这并不像您想要的那样完整,但它是一个开始。

With --merged, only branches merged into the named commit (i.e. the branches whose tip commits are reachable from the named commit) will be listed.

使用--merged,只会列出合并到命名提交中的分支(即可以从命名提交访问其提示提交的分支)。

回答by Karl Wilbur

I have a similar issue. I want to remove all local branches that were tracking remote branches that are now deleted. I am finding that git remote prune originwas insufficient to remove the branches that I want gone. Once the remote is deleted, I want the local to go away too. Here is what worked for me:

我有一个类似的问题。我想删除所有跟踪现在已删除的远程分支的本地分支。我发现这git remote prune origin不足以删除我想要的分支。删除遥控器后,我也希望本地也消失。这是对我有用的:

From my ~/.gitconfig:

从我的~/.gitconfig

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print }' | 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 }'"'"' | xargs -r git branch -d'

NOTE: I changed the -dto -Din my actual configuration, because I don't want to hear Git complain about unmerged branches. You maywant this functionality as well. If so, simply use -Dinstead of -dat the end of that command.

注意:我在实际配置中更改了-dto -D,因为我不想听到 Git 抱怨未合并的分支。您可能也需要此功能。如果是这样,只需在该命令的末尾使用-D而不是-d

Also, FWIW, your global configuration file would almost always be ~/.gitconfig.

此外,FWIW,您的全局配置文件几乎总是~/.gitconfig.

(OS X Fix)

(OS X 修复)

As written, this does not work on OS X because of the use of xargs -r(thanks, Korny).

正如所写,这在 OS X 上不起作用,因为使用了xargs -r(谢谢,Korny)。

The -ris to prevent xargsfrom running git branch -dwithout a branch name, which will result in an error message "fatal: branch name required". If you don't mind the error message, you can simply remove the -rargument to xargsand you're all set.

-r是为了防止xargsgit branch -d没有分支名称的情况下运行,这将导致错误消息“ fatal: branch name required”。如果您不介意错误消息,您可以简单地删除-r参数,xargs就可以了。

However, if you don't want to see an error message (and really, who could blame you) then you'll need something else that checks for an empty pipe. If you might be able to use ifnefrom moreutils. You would insert ifnebefore xargs, which will stop xargsfrom running with empty data. NOTE: ifneconsiders anythingto be not empty, this includes blank lines, so you may still see that error message. I've not tested this on OS X.

但是,如果您不想看到错误消息(实际上,谁会责怪您),那么您将需要其他东西来检查空管道。如果您可以使用moreutils 中ifne。您将插入ifnebefore xargs,这将停止xargs运行空数据。注意ifne认为任何内容都不是空的,这包括空行,因此您可能仍会看到该错误消息。我没有在 OS X 上测试过这个。

Here is that git configline with ifne:

这是那条git config线ifne

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print }'"'"' | ifne xargs git branch -d'

回答by jthill

Late edit:

后期编辑:

Better is

更好的是

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


On GNU/anything

关于 GNU/任何东西

for b in `git branch|sed s,..,,`; do
    git config --get branch.$b.remote|sed Q1 && echo git branch -D $b
done

If more than a handful of branches were likely, there'd be better ways, using comm -23on the output of git branch|sed|sortand git config -l|sed|sort.

如果超过了一把树枝很可能有会是更好的方式,使用comm -23上的输出git branch|sed|sortgit config -l|sed|sort

回答by ebr

This works for me:

这对我有用:

git branch -vv | grep -v origin

git branch -vv | grep -v origin

(if your remote is named anything other than origin, substitute that).

(如果您的遥控器命名为 origin 以外的任何名称,请替换它)。

This will list all the branches that aren't tracking a remote, which sounds like what you're looking for.

这将列出所有未跟踪遥控器的分支,这听起来像您要查找的内容。

回答by fiorentinoing

I synthetise my own Git command to get the origin/***: gonebranches:

我合成了自己的 Git 命令来获取origin/***: gone分支:

git remote prune origin && git branch -vv | cut -c 3- | grep ': gone]' | awk '{print }' | xargs -n1 -r echo git branch -d

git remote prune origin && git branch -vvwill print branches in verbose mode.

git remote prune origin && git branch -vv将以详细模式打印分支。

cut -c 3-will remove very first characters.

cut -c 3-将删除第一个字符。

grep ': gone]'will print only the goneremote branches.

grep ': gone]'将只打印消失的远程分支。

awk '{print $1}'will print the branch name.

awk '{print $1}'将打印分支名称。

xargs -n1 -r echo git branch -dwill print the git branch -dcommand to remove branches (-n1 will manage one command per time, -r to avoid issuing command if no branch is present).

xargs -n1 -r echo git branch -d将打印git branch -d删除分支的命令(-n1 将每次管理一个命令,-r 以避免在不存在分支时发出命令)。

HINT:remove the "echo" command to runthe commands instead of print only, I left this in the command to check commands before issuing to git.

提示:删除“echo”命令以运行命令而不是仅打印,我将其留在命令中以在向 git 发出之前检查命令。

HINT 2:issue git branch -Dif and only if you are sure you want to remove unmerged branches

提示 2:git branch -D当且仅当您确定要删除未合并的分支时才发出

回答by grahamesd

Here is something I have used in PowerShell with comments to explain what it's doing. In an attempt to make it clear what's going on, I've not used any abbreviated PowerShell commands (aliases). Feel free to compress it to your desired level of crypticness :)

这是我在 PowerShell 中使用的一些注释来解释它在做什么。为了弄清楚发生了什么,我没有使用任何缩写的 PowerShell 命令(别名)。随意将其压缩到您想要的神秘程度:)

$verboseList = @(git branch -vv)
foreach ($line in $verboseList)
{
    # Get the branch name
    $branch = [regex]::Match($line, "\s(\S+)\s").Captures.Groups[1].Value
    # Check if the line contains text to indicate if the remote is deleted
    $remoteGone = $line.Contains(": gone]")
    # Check if the line does not contain text to indicate it is a tracking branch (i.e., it's local)
    $isLocal = !($line.Contains("[origin/"))
    if ($remoteGone -or $isLocal)
    {
        # Print the branch name
        $branch
    }
}

回答by nbergen

Rough PowerShell implementation (if origin is your only remote):

粗略的 PowerShell 实现(如果 origin 是你唯一的远程):

@($branches = git br -r; git branch | %{ echo $_ | sed 's/..//' }) `
   | %{ if (($branches | ss "origin/$_") -eq $null) { `
          echo "git branch -D $_" `
        } `
      }

回答by Reid

Combining a few of the existing answers:

结合一些现有的答案:

[alias]
        branch-local = !git branch -vv | cut -c 3- | egrep '([0-9a-f]{7} [^[])|(: gone\])' | sed -E 's/(^.+[0-9a-f]{7} (\[.+\])?).*$/\1/'

E.g.:

例如:

$ git branch-local
autogen_autoreconf      fcfb1c6 [github/autogen_autoreconf: gone]
autotools_documentation 72dc477 [github/autotools_documentation: gone]
cray-mpich-messy        2196f4b
epel-sphinx             cfda770
lammps                  07d96a7 [github/lammps: gone]
lark-error              9ab5d6c [github/lark-error: gone]
no-root2                c3894d1
openmpi-cray            69326cf [github/openmpi-cray: gone]
shellcheck-cleanup      40d90ec
travis-python36         cde072e
update_vagrant_default  4f69f47 [github/update_vagrant_default: gone]
web-docs                e73b4a8