問題:リモートがないローカルブランチをすべて削除する方法が必要です。ブランチの名前を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を作成するつもりです。
助けていただければ幸いです!ありがとう
最近、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
このきれいにフォーマットされた出力が得られたら、cut
とawk
を介してパイプしてリストを取得するのと同じくらい簡単です。
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 }'
git branch
(オプションなし)はローカルブランチのみをリストしますが、リモートブランチを追跡しているかどうかはわかりません。
通常、これらのローカルブランチはmaster
にマージされたら削除する必要があります( このgit-sweepの問題 を参照)。
git branch --merged master | grep -v master | xargs git branch -d
これはあなたが望むほど完全ではありませんが、始まりです。
--merged
、名前付きコミットにマージされたブランチ(つまり、名前付きコミットからチップコミットが到達可能なブランチ)のみがリストされます。
同様の問題があります。現在削除されているリモートブランチを追跡していたローカルブランチをすべて削除したい。 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 を使用できる場合。 ifne
をxargs
の前に挿入すると、xargs
が空のデータで実行されなくなります。 [〜#〜] note [〜#〜]:ifne
はanythingが空でないと見なします。これには空白行が含まれます。それでもそのエラーメッセージが表示される場合があります。 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'
後期編集:より良い
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
。
これは私のために働く:
git branch -vv | grep -v Origin
(リモートの名前がOrigin以外の場合は、それを置き換えます)。
これにより、リモートを追跡していないすべてのブランチがリストされます。これは、探しているもののように聞こえます。
私は自分の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 -d
はgit branch -d
ブランチを削除するコマンド(-n1は毎回1つのコマンドを管理し、-rはブランチが存在しない場合にコマンドを発行しないようにします)
HINT:から "echo"コマンドを削除runコマンドを印刷のみではなく、gitに発行する前にコマンドをチェックするコマンドに残しました。
ヒント2: issue git branch -D
マージされていないブランチを削除することが確実な場合にのみ
大まかなpowershell実装:(Originが唯一のリモートの場合)
@($branches = git br -r; git branch | %{ echo $_ | sed 's/..//' }) `
| %{ if (($branches | ss "Origin/$_") -eq $null) { `
echo "git branch -D $_" `
} `
}
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
}
}