リモートなしですべてのローカルブランチを一覧表示


91

問題:リモートを持たないローカルブランチをすべて削除する方法が必要です。ブランチの名前をパイプでつなぐのは簡単git branch -D {branch_name}ですが、そもそもそのリストを取得するにはどうすればよいですか?

例えば:

リモートなしで新しいブランチを作成します。

$ git co -b no_upstream

すべてのブランチを一覧表示しますが、リモートを備えたブランチは1つだけです

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

no_upstream答えを得るためにどのコマンドを実行できますか?

私は走ることができます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>...]'

ただし、これはエラーであるため、使用したり、他のコマンドにパイプしたりすることはできません。私はこれをシェルスクリプトのエイリアスとして使用するか、次のgit-delete-unbranchedような非常に単純なGemを作成するつもりです。git-branch-delete-orphans



回答:


103

私は最近git branch -vvgit branchコマンドの「非常に冗長な」バージョンを発見しました。

ブランチが存在する場合は、リモートブランチとともに次の形式で出力します。

  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

この適切にフォーマットされた出力を取得したら、それをパイプでつなぎ、リストを取得するのcutと同じくらい簡単awkです。

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

結果は次のようになります。

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

このcut部分は、データを*に渡す前に、出力から最初の2文字(を含む)を削除することによってデータを正規化しますawk

awk3番目の列に角括弧がない場合、その部分は最初の列を印刷します。

ボーナス:エイリアスを作成する

グローバル.gitconfigファイル(または任意の場所)にエイリアスを作成して、実行を簡単にします。

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

重要:バックスラッシュはエイリアスでエスケープする必要があります。そうしないと、無効なgitconfigファイルが作成されます。

ボーナス:リモートフィルタリング

何らかの理由で、ブランチごとに複数のトラッキングリモコンがある場合は、チェックするリモコンを簡単に指定できます。awkパターンにリモート名を追加するだけです。私の場合、それはorigin私がこれを行うことができるようにするためです:

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

WIP:とにかくそれは何ですか..?それはstashコマンドが作成するものではありませんか..?
igrek 2017年

@igrekこれはコミットメッセージで使用したプレフィックスです。gitに固有のものはありません。
ジェレミーベイカー

私が行うときgit branch -vv、リモートブランチが存在していて、私の地元の支店と一致した場合でも、私は見ていないだろう[origin/branch-name]結果と一緒に。私はdiff実際にローカルのみのものを理解するためにブランチの2つのリストを作成する必要がありました。
ryantuck

git branch -vv | grep -v origin/私には十分です
慌てる必要はありません

2
これは、マークされたリモートブランチを見逃しませんgoneか?
リード

36

git branch (オプションなしで)ローカルブランチのみが一覧表示されますが、リモートブランチを追跡しているかどうかはわかりません。

通常、これらのローカルブランチは、マージされたら削除する必要がありますmastergit-sweepのこの号に見られるように):

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

これはあなたが望むほど完全ではありませんが、それは始まりです。

を使用--mergedすると、名前付きコミットにマージされたブランチ(つまり、名前付きコミットからチップコミットに到達できるブランチ)のみが一覧表示されます。


1
ローカルブランチのないリモートブランチも含めるには、を使用しますgit branch -a --merged
acumenus 2017年

21

同様の問題があります。現在削除されているリモートブランチを追跡していたすべてのローカルブランチを削除したいと思います。git remote prune origin削除したいブランチを削除するには不十分であることがわかりました。リモコンが削除されたら、ローカルも削除してほしい。これが私のために働いたものです:

私から~/.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がマージされていないブランチについて文句を言うのを聞きたくないので、実際の構成で-dをに変更しまし-Dた。あなたは可能としても、この機能が欲しいです。その場合は、そのコマンドの最後では-Dなく、単に使用-dしてください。

また、FWIW、グローバル構成ファイルはほとんどの場合~/.gitconfig。です。

(OS X修正)

書かれているように、これはxargs -r(thanks、Korny)を使用しているため、OSXでは機能しません。

これ-rは、ブランチ名なしでxargs実行されgit branch -dないようにするためのものfatal: branch name requiredです。これにより、エラーメッセージ「」が発生します。エラーメッセージを気にしない場合は、への-r引数を削除するだけで、xargsすべて設定できます。

ただし、エラーメッセージ(そして実際には誰があなたを責める可能性があるか)を見たくない場合は、空のパイプをチェックする何か他のものが必要になります。moreutilsからifneを使用できる可能性がある場合。のifnexargsに挿入すると、xargs空のデータでの実行が停止します。ifneみなし何も空ではないことにするが、これは空白行が含まれて、あなたはまだそのエラーメッセージが表示されることがあります。私はこれをOSXでテストしていません。

これがそのgit configifneです:

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

1
これを「gitconfig--global ...」コマンドに変換することは可能ですか?インストラクション/ how-to-wiki-for-dummiesの観点から、「git configファイルを見つけ、エディターを使用して編集してからコマンドを実行する」と言う代わりに、簡単に渡すことができます
Kannan Ekanath 2017


知っておくと良い。OSXの「空の場合は実行しない」オプションがどうなるかわかりません。
Karl Wilbur

18

後期編集:

良いです

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

GNU /何でも

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

一握り以上のブランチがありそうな場合comm -23は、との出力を使用して、より良い方法がgit branch|sed|sortありgit config -l|sed|sortます。


1
@nmr s/git。*Q1/ test $(git config --getbranch。$ b.remote | sed q | wc -1)= 1 /
jthill 2014

15

これは私のために働きます:

git branch -vv | grep -v origin

(リモコンの名前がオリジン以外の場合は、それに置き換えてください)。

これにより、リモートを追跡していないすべてのブランチが一覧表示されます。これは、探しているもののように聞こえます。


2
これにより、以前はリモートがあったが、を実行してももう存在しないブランチが一覧表示されますgit fetch --prune
rusinaRange 2017年

2
IMO、「origin」を除外するのではなく、「:gone]」を探す方が良い
fiorentinoing

4

origin/***: goneブランチを取得するために、独自のGitコマンドを合成します。

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

git remote prune origin && git branch -vv 詳細モードでブランチを印刷します。

cut -c 3- 最初の文字を削除します。

grep ': gone]'なくなったリモートブランチのみを印刷します。

awk '{print $1}' ブランチ名を出力します。

xargs -n1 -r echo git branch -dgit branch -dブランチを削除するコマンドを出力します(-n1は一度に1つのコマンドを管理し、-rはブランチが存在しない場合にコマンドを発行しないようにします)。

ヒント:「echo」コマンドを削除して、印刷のみではなくコマンドを実行します。これをコマンドに残して、gitに発行する前にコマンドを確認しました。

ヒント2:git branch -Dマージされていないブランチを削除することが確実な場合にのみ発行します


これから私は自分の個人的なgitを削除しました
fiorentinoing

1
これは、はるかに私が見つけたクリーンなソリューション、素敵!私は勉強awkに時間を費やしたことがありません、私はあなたがそれをすることができるとは知りませんでした。
adamjc

2

これは、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
    }
}

0

既存の回答のいくつかを組み合わせる:

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

例えば:

$ 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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.