web-dev-qa-db-ja.com

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

問題:リモートがないローカルブランチをすべて削除する方法が必要です。ブランチの名前を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にエイリアスされたシェルスクリプトとして使用するか、git-branch-delete-orphansのような超シンプルなGemを作成するつもりです。

助けていただければ幸いです!ありがとう

67
JC Denton

最近、git branch -vvコマンドの「非常に冗長な」バージョンであるgit 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

このきれいにフォーマットされた出力が得られたら、cutawkを介してパイプしてリストを取得するのと同じくらい簡単です。

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

次の出力が得られます。

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

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

3番目の列に角かっこがない場合、awk部分は最初の列を出力します。

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

グローバル.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 }'
80
Jeremy Baker

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

通常、これらのローカルブランチはmasterにマージされたら削除する必要があります( このgit-sweepの問題 を参照)。

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

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

--merged、名前付きコミットにマージされたブランチ(つまり、名前付きコミットからチップコミットが到達可能なブランチ)のみがリストされます。

29
VonC

同様の問題があります。現在削除されているリモートブランチを追跡していたローカルブランチをすべて削除したい。 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'

[〜#〜] note [〜#〜]:聞きたくないので、実際の設定で-d-Dに変更しましたGitはマージされていないブランチについて文句を言います。あなたもこの機能が必要な場合があります。その場合、そのコマンドの最後で-Dの代わりに-dを使用します。

また、FWIW、グローバル設定ファイルはほとんどの場合~/.gitconfigになります。

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

-rは、xargsがブランチ名なしでgit branch -dを実行しないようにするためのもので、エラーメッセージ "fatal: branch name required"が表示されます。エラーメッセージを気にしない場合は、xargsへの-r引数を削除するだけで十分です。

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

git config行とifneは次のとおりです。

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

後期編集:より良い

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

16
jthill

これは私のために働く:

git branch -vv | grep -v Origin

(リモートの名前がOrigin以外の場合は、それを置き換えます)。

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

11
ebr

私は自分のgitコマンドをsinthetizeしてOrigin/***: goneブランチ:

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]'は、goneリモートブランチのみを出力します

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

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

HINT:から "echo"コマンドを削除runコマンドを印刷のみではなく、gitに発行する前にコマンドをチェックするコマンドに残しました。

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

2
fiorentinoing

大まかなpowershell実装:(Originが唯一のリモートの場合)

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

PowerShellで何をしているのかを説明するコメントとともに、これを使用しました。何が起こっているのかを明確にするために、短縮されたPSコマンドは使用していません。お望みの暗号レベルに自由に圧縮してください:)

$verboseList = @(git br -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
    }
}
2
grahamesd