リモートに存在しない追跡ブランチを削除する


1173

リモートで同等のものが存在しないすべての追跡ブランチを削除する簡単な方法はありますか?

例:

ブランチ(ローカルおよびリモート)

  • 主人
  • 起源/マスター
  • origin / bug-fix-a
  • origin / bug-fix-b
  • origin / bug-fix-c

ローカルでは、私はマスターブランチしか持っていません。次に、bug-fix-aで作業する必要があるので、チェックアウトして作業し、変更をリモートにプッシュします。次に、bug-fix-bでも同じことを行います。

ブランチ(ローカルおよびリモート)

  • 主人
  • バグ修正-a
  • バグ修正b
  • 起源/マスター
  • origin / bug-fix-a
  • origin / bug-fix-b
  • origin / bug-fix-c

現在、私はローカルブランチmasterbug-fix-abug-fix-bを持っています。マスターブランチのメンテナーは私の変更をマスターにマージし、彼がすでにマージしたすべてのブランチを削除します。

したがって、現在の状態は次のとおりです。

ブランチ(ローカルおよびリモート)

  • 主人
  • バグ修正-a
  • バグ修正b
  • 起源/マスター
  • origin / bug-fix-c

次に、リモートリポジトリに表示されなくなったブランチ(この場合はbug-fix-abug-fix-b)を削除するコマンドを呼び出します。

それは既存のコマンドgit remote prune originに似ていgit local prune originますが、もっと似ています。

回答:


1282

git remote prune origin リモート上にないブランチを追跡するプルーン。

git branch --merged 現在のブランチにマージされたブランチをリストします。

xargs git branch -d 標準入力にリストされているブランチを削除します。

によってリストされgit branch --mergedたブランチを削除するときは注意してください。リストには、master削除したくない他のブランチを含めることができます。

ブランチを削除する前にリストを編集する機会を自分に与えるには、1行で次のようにします。

git branch --merged >/tmp/merged-branches && \
  vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

17
マージされたブランチの最初の行は* master私のシステムにあります。次のコマンドは、私の仕事:git branch -d $(git branch --merged |tail -n +2)
Trendfischer

99
私がついているならdevelopgit branch --merged含まれていますmaster!あなたはおそらく(間違いなく!)それを削除したくないでしょう。またgit branch -d、小文字が-d「安全な削除」を意味する場所である必要があると思います。たとえば、マージされた場合のみ削除します。
thom_nic 2015年

11
そこには改善されたソリューションが提供されているようです。
Sergey Brunov 2016年

34
削除されたマージは便利ですが、「リモートにないブランチを削除する」とは異なります。
dlsso

11
マスターを除外するだけで使用はgrep:git branch --merged | grep -v "master" >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
geniass

591

コマンドの後

git fetch -p

実行時にリモート参照を削除します

git branch -vv

リモートステータスとして「gone」が表示されます。例えば、

$ git branch -vv
  master                 b900de9 [origin/master: behind 4] Fixed bug
  release/v3.8           fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
  release/v3.9           0d680d0 [origin/release/v3.9: behind 2] Updated comments
  bug/1234               57379e4 [origin/bug/1234: gone] Fixed bug

したがって、リモートになっているローカルブランチを削除する簡単なスクリプトを記述できます。

git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done

上記では「porcelain」コマンドgit branchを使用して、上流のステータスを取得していることに注意してください。

このステータスを取得する別の方法はgit for-each-ref、補間変数を指定して「配管」コマンドを使用%(upstream:track)することです。これは[gone]上記と同じです。

この方法は、コミットメッセージの一部を誤って照合するリスクがないため、多少安全です。

git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}'); do git branch -D $branch; done

8
@KrzysztofWende-Solarisおよび一部のBSDおよび一部のOS Xでは使用できません:)
jww

4
これは、最後のコミットメッセージで「行った」ブランチをすべて削除するように見えます。
dlsso

11
@dlsso最後のコミットメッセージに文字列 ":gone]"が含まれている場合、はい、それも削除されます。コミットメッセージを取り除くために追加のawk / gawkを使用することで、単純さを犠牲にしてより堅牢にすることができます。git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
jason.rickman

2
私の以前のコメント(質問)に答えて、現在のブランチは最初のフィールドとして*を持っています。「ゴーン」ブランチのリストにも含まれている場合、$ 1が*割り当てられ、ファイル名とフォルダー名を吐き出すawkを含むファイル仕様として解釈されます。私はgrep式を削除し、awkにすべてのフィルタリングを実行させましたawk '/: gone]/{if ($1!="*") print $1}'。これは期待どおりに動作するようになりました。
rhaben

5
@ahmedbhsコマンドは一重引用符を使用するため、コマンド全体を囲むには二重引用符を使用する必要があります。また、シェルコマンドであるgitエイリアス(このコマンドのように)には最初に!が必要です。これは私にとっては機能します:test = "!git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
jason.rickman

306

これらの回答のほとんどは、実際には元の質問に答えるものではありません。私はたくさん掘りましたこれが私が見つけた最もクリーンな解決策でした。その答えのもう少し完全なバージョンを次に示します。

  1. デフォルトのブランチを確認してください。通常git checkout master
  2. 走る git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

説明:

追跡ブランチをプルーニングし、それらが「なくなっている」ことを示すローカルブランチを削除することで機能します。 git branch -vvます。

ノート:

言語が英語以外に設定されている場合はgone、適切な単語に変更する必要があります。ローカルのみのブランチは変更されません。リモートで削除されているがマージされていないブランチには、通知が表示されますがローカルでは削除されません。それらも削除したい場合は、に変更-dしてください-D


2
フランスのOSがなくなったため、disparueによって変更する必要があります
Mohamed EL HABIB 2017

4
英語を強制するには、gitブランチの前にLANG = en_USを追加する必要があります。git fetch --prune && LANG = en_US git branch -vv | awk '/:gone] / {print $ 1}' | xargs gitブランチ-d
Mohamed EL HABIB 2017

3
git checkout master && ...コマンドの最初に追加します。
iarroyo 2017年

2
これは、削除されるはずのブランチにいる場合は危険です。その場合、最初の列は「*」であり、xargsに渡されます。これを改善するには、出力をawkに渡す前に「*」文字を削除します。sed -e 's / ^ * //'
meeee

6
気をつけて!すべてのローカルブランチを削除することになるエッジケースがあります。リモートで削除されたブランチを現在使用している場合、の出力はgit branch -vvアスタリスクで始まり、最終的にが実行されgit branch -d *ます。ここでは、アスタリスクを持つ行を無視するパッチを当てたバージョンがある:git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
KCM

210

私は通常、すでに16個の回答がある質問には答えませんが、他のすべての答えは間違っており、正しい答えはとても簡単です。質問には、「リモートで同等のものが存在しないすべての追跡ブランチを削除する簡単な方法はありますか?」とあります。

「単純」とは、脆弱性や危険性がなく、すべての読者が持っているわけではないツールに依存せずに、すべてを一度に削除することを意味する場合、正しい答えは次のとおりです。

いくつかの答えは単純ですが、彼らは求められたことをしません。他の人は求められたことを行いますが、単純ではありません。すべてのシステムに存在するとは限らない、テキスト操作コマンドまたはスクリプト言語によるGit出力の解析に依存しています。その上、ほとんどの提案は磁器コマンドを使用しており、その出力はスクリプトによって解析されるようには設計されていません(「磁器」とは人間の操作を目的としたコマンドを指します。スクリプトは下位レベルの「配管」コマンドを使用する必要があります)。

参考文献:


これを安全に行うには、質問のユースケース(サーバーで削除されたがローカルブランチとして存在するガベージコレクショントラッキングブランチ)で、高レベルのGitコマンドのみを使用する場合、

  • git fetch --prune(またはgit fetch -p、これはエイリアスであるか、git prune remote originフェッチせずに同じことを行うため、ほとんどの場合、たいていは必要ありません)。
  • 削除されたと報告されているすべてのリモートブランチに注意してください。または、後でそれらを見つけるにはgit branch -v(孤立した追跡ブランチはすべて[[gone] "とマークされます)。
  • git branch -d [branch_name] 孤立した追跡ブランチごとに

(これは他の回答のいくつかが提案しているものです)。

ソリューションをスクリプト化する場合for-each-refは、ここからが出発点です。MarkLongairのここでの回答と別の質問に対するこの回答のように、シェルスクリプトループを記述したり、xargsや何かを使用したりせずに解決策を利用する方法はありません。


背景説明

何が起こっているのかを理解するには、ブランチを追跡する状況では、ブランチが1つではなく3つあることを理解する必要があります。(そして、「ブランチ」は単にコミットへのポインタを意味することを思い出してください。)

追跡ブランチを指定するfeature/Xと、リモートリポジトリ(サーバー)にこのブランチがあり、それを呼び出しますfeature/X。ローカルリポジトリにはブランチがremotes/origin/feature/Xあります。つまり、「これは、リモートがその機能/ Xブランチについて、前回話したときのことです」という意味です。最後に、ローカルリポジトリには、feature/X最新のコミットを指すブランチがあり、 "追跡"remotes/origin/feature/X、引っ張ったり押したりして、それらを整列させたままにできることを意味します。

ある時点で、誰かがfeature/Xリモートでを削除しました。その瞬間から、あなたはあなたのローカルfeature/X(機能Xでの作業はおそらく終了しているのでおそらくもう望まないでしょう)を残し、あなたのローカルremotes/origin/feature/Xはサーバーのブランチの状態を記憶することだけだったので確かに役に立たない。

そしてGitはあなたに冗長なものを自動的にクリーンアップさせますremotes/origin/feature/X-それが何をするかですgit fetch --prune-しかし何らかの理由でそれはあなたがあなた自身のものを自動的に削除することを許しませんfeature/X...あなたがfeature/Xまだ孤立した追跡情報を含んでいるので、それは情報を持っています完全にマージされた以前の追跡ブランチを識別するため。(結局のところ、自分で操作できるよう情報が得られます。)


3
これははるかに安全な答えです。さらに、選択した回答とは異なり、「スカッシュとマージ」ワークフローを使用する場合にも機能します。
ジェイクレビット

3
これは実際には「消えたブランチを見つける方法」という質問の簡単な部分(および2015年にjason.rickmanによってすでに投稿されたものと同じコマンドで)にのみ答えますが、すべてのブランチを手動で削除するように指示します。したくない。
Voo 2018年

4
@Vooそれが答えの要点です。それを行う方法を教えるのではなく(それは単なるボーナスです)ではなく、答えは簡単で簡単な方法はないということです。それが策定されたときの質問に対する正しい答えはどれですか。
Andrew Spencer

1
「これを安全に実行したい場合は、質問のユースケースで..」-最初の段落のほとんどの主張を否定します。「[Git]は、手動で操作できる情報を提供します」-私たちはプログラマーなので、情報をリスト(表示)として与えられても、タスクはまだ単純です(例:)xargs。ありgit alias症例数を簡素化します。
user2864740

2
@ user2864740一部の読者は、小さなbashスクリプトの記述は「シンプル」の定義内にあると考えるかもしれません。それは完全に防御可能な立場ですが、私は2段落目で「シンプル」の独自の解釈を与え、残りの答えは一貫していますそれと。そして、私の制限的な解釈を守るために、すべてのGitユーザーが持っている、xargsまたはbashしているわけではありません。マイクロコーディングの課題を探しているわけではないので、実際の目標から離れることなく、安全に適用できます。 。
Andrew Spencer

52

私はここで答えを見つけました: マージされたすべてのgitブランチを削除するにはどうすればよいですか?

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

私たちはマスターを保つことを確認してください

最初masterのブランチのgrep後に別のブランチを追加することで、、または他のブランチが削除されないようにすることができます。その場合、あなたは行くでしょう:

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

だから我々は維持したい場合masterdevelopおよびstaging例えば、我々は行くだろう。

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

これをエイリアスにします

少し長いので、.zshrcやにエイリアスを追加したいかもしれません.bashrc。鉱山が呼び出されますgbpurge(の場合git branches purge):

alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'

次に.bashrcまたはをリロードします.zshrc

. ~/.bashrc

または

. ~/.zshrc

8
便利ですが、「リモートにないブランチを削除する」とは
異なります

素晴らしい答え@karlingen、私はこれを私のすべての開発環境にわたってgbpurgeとして永久に持っています
Peter Dolan

50

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リファレンス

Select-String -Pattern ": gone]" リモートから削除されたレコードのみを取得します。

% { $_.toString().Trim().Split(" ")[0]} ブランチ名を取得する

% {git branch -d $_} ブランチを削除します


3
おかげで、ブランチ名の前の2つのスペースを削除するために、.Trim()アフターを追加する.toString()必要がありました。
マシュー

2
このコマンドをありがとう。を変更するgit branch -d必要git branch -Dがありました。ブランチが完全にマージされないというエラーが発生します。
markieo

1
-あなたはおそらくすでにこのことを知っているが、他の誰のため@markieo git branch -D破壊し、あなたがまだプッシュされていないことを地元の仕事を削除します。-dは常に安全-Dです。に注意してください。
Nate Barbettini、

33

他のほとんどのソリューションで「なくなった」のパターンマッチングは、私にとって少し怖いものでした。安全のために、これは--formatフラグを使用して各ブランチの上流の追跡ステータスを引き出します

私はWindows対応のバージョンが必要だったので、Powershellを使用して "gone"としてリストされているすべてのブランチを削除します。

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }

最初の行には、上流のブランチが「なくなった」ローカルブランチの名前がリストされています。次の行は空白行(「なくなった」ブランチの出力)を削除し、ブランチ名をコマンドに渡してブランチを削除します。


6
--formatオプションはかなり新しいのようです。gitを2.10.somethingから2.16.3にアップグレードして取得する必要がありました。これは、Linuxっぽいシステムのための私の修正である:git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
BXM

2
これはこれまでのところ最良の解決策です。1つの提案はを使用することrefname:shortです。次に、行を削除できます% { $_ -replace '^refs/heads/', '' }
ioudas

2
これは、Windowsに最適なソリューションです。私はそれがより読みやすいです。この原因のようにそれを使用していますgit branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ }おそらく、また使用することをお勧め-dの代わりに-D。リモートに存在しなくなったブランチでは、強制削除は必要ありません。
ルバノフ

31

マスターにマージされたすべてのブランチを削除しますが、マスター自体は削除しないでください。

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

またはエイリアスを追加します。

alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"

説明:

git checkout master チェックアウトマスターブランチ

git pull origin master ローカルブランチにすべてのリモート変更がマージされていることを確認してください

git fetch -p 削除されたリモートブランチへの参照を削除する

git branch -d $(git branch master --merged | grep master -v) マスターにマージされたすべてのブランチを削除しますが、マスター自体は削除しないでください


3
これは非常に便利ですが、リモートにプッシュされたことがないブランチも削除されます。違いのみをリストし、本当に削除したいものをgit branch -Dコマンドにコピーする方が安全です
Zefiryn

明確にするために、Zefirynはワンライナーの一部ではない-Dオプションの使用について言及しています。
cs01 14

1
または、小文字のjuseを使用すると、git branch -dプッシュされていないブランチに関する警告が表示されます。
acme

16
git fetch -p

これにより、リモートに存在しなくなったブランチがプルーニングされます。


64
これにより、リモート参照は削除されますが、ローカルブランチ自体は削除されません。便利なコマンドですが、これがOPの質問に答えるとは思いません。
thataustin 2014年

何?これにより、ローカルのブランチが削除されます。
アレックスホール

1
@AlexHallリモートリポジトリにはブランチがありXます。あなたgit checkout X; これで、リポジトリに(ローカル)トラッキングブランチXとリモートブランチがありorigin/Xます。リモートリポジトリが削除しXます。あなたgit fetch-p; ローカルリポジトリにあるだけでなくorigin/XX削除されています。それはあなたが言っていることですか?
Andrew Spencer

16

パトリックの答えから大きく引き出す、まだ別の山の答え(出力のどこgone]が一致するかについてのあいまいさを排除しているように見えるので私は好きですgit branchますが、* nixの曲がりを追加しています。

最も単純な形で:

git branch --list --format \
  "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" \
  | xargs git branch -D

私はこれgit-goneを私のパス上のスクリプトにまとめました:

#!/usr/bin/env bash

action() {
  ${DELETE} && xargs git branch -D || cat
}

get_gone() {
  git branch --list --format \
    "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)"
}

main() {
  DELETE=false
  while [ $# -gt 0 ] ; do
    case "${1}" in
      (-[dD] | --delete) DELETE=true ;;
    esac
    shift
  done
  get_gone | action
}

main "${@}"

注意- --formatオプションはかなり新しいようです。gitを2.10.somethingから2.16.3にアップグレードして取得する必要がありました。

編集:refname:shortからの提案を含めるように調整されましたベンジャミンW

NB2-私はbash、つまりハッシュバングでのみテストしましたが、おそらくに移植可能shです。


最初の行でsedを使ってその部分をスキップできません%(refname:short)か?
ベンジャミンW.

私のために働くようです、そして私は今それをきちんとしたGitエイリアスとして持っています-ここでそれらすべての最もきれいな解決策!
ベンジャミンW.

2.13が導入されました--formatsed一部をスキップする別の方法は、を使用することgit update-ref -dです。これはおそらくやや安全でgit for-each-refはないことに注意してください--shell
gsnedders

すばらしい答え--formatです。これを自分で行うのに悩んでいるときに自分の質問に答えるのに役立ちます。ただ一つの質問:なぜ#!bash?ここにあるものはすべてsh、私にとっては移植性があるように見えます。
Toby Speight

これは単なる私の定型文であり、他の場所ではテストしていません。
bxm

15

マスターを除くすべてのローカルブランチをクリアして開発するためのいくつかの単純な1行に役立つ場合があります

git branch | grep -v "master" | grep -v "develop" | xargs git branch -D

素晴らしい答え!'git branch | grep -v "master" | grep -v "develop"コマンドの削除部分を追加する前に、この種のものを簡単に操作できることが好きです。👏😊
finneycanhelp

しかし、これは上記の質問には答えません。これにより、リモートがまだ存在していてもブランチが削除されます。
Jim.B

13

これにより、ローカルマスター参照と現在使用されているものを除いて、マージされたすべてのローカル分岐が削除されます。

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

また、これにより、「origin」によって参照されるリモートリポジトリからすでに削除されているすべてのブランチが削除されますが、「remotes / origin」でローカルに使用できます。

git remote prune origin

git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d 説明:私は交換好むgit branch --mergedによりgit branch -vv以前はので、ステータス(ゴーン)を表示するためにgit branch --mergedも、マスター表示することができます
jpmottin

13

これを行うための組み込みコマンドはないと思いますが、以下を実行しても安全です。

git checkout master
git branch -d bug-fix-a

を使用すると-d、gitは、ブランチHEADまたはその上流のリモート追跡ブランチに完全にマージされない限り、ブランチの削除を拒否します。したがって、常に出力をループして、git for-each-ref各ブランチを削除することができます。このアプローチの問題は、履歴が含まれているbug-fix-dという理由だけで削除されたくないと思うことorigin/bug-fix-dです。代わりに、次のようなスクリプトを作成できます。

#!/bin/sh

git checkout master &&
for r in $(git for-each-ref refs/heads --format='%(refname:short)')
do
  if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ]
  then
    if [ "$r" != "master" ]
    then
      git branch -d "$r"
    fi
  fi
done

警告:このスクリプトはテストしていません-注意して使用してください...


私は自由にスクリプトを編集しました。それでも保証はありませんが、動作し、現在は動作しているようです。
fwielstra 2014

13

TL; DR:

リモート上にないすべてのローカルブランチを削除する

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

リモート上になく、完全にマージされており、以前の多くの回答で述べられているように使用さていないすべてのローカルブランチを削除します。

git fetch -p && git branch --merged | grep -v '*' | grep -v 'master' | xargs git branch -d

説明

  • git fetch -p リモートに存在しないすべてのブランチをプルーニングします
  • git branch -vv ローカルブランチを印刷し、剪定ブランチはタグ付けされます gone
  • grep ': gone]' なくなったブランチのみを選択します
  • awk '{print $1}' 出力をフィルタリングしてブランチの名前のみを表示します
  • xargs git branch -D すべてのライン(ブランチ)をループし、このブランチを強制的に削除します

完全にマージされていないブランチについては、なぜそうでなければgit branch -Dならないgit branch -dでしょう。

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

1
マスターの代わりにリモートと言いたいですか?
tinos

8

あなたはこれを行うことができます:

git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d

7

上記の情報に基づいて、これは私のために働きました:

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

areを使用してすべてのローカルブランチを削除します ': gone] 'リモートにある。


1
これは、最後のコミットメッセージで「行った」ブランチをすべて削除するように見えます。
dlsso

またgone、名前のどこかにあるブランチを削除します。
bfontaine

3
"gitブランチ-D gitブランチ-vv | grep ':gone]' | awk '{print $ 1}' | xargs`"これは私のために働きました。
Muthu Ganapathy Nathan 2016

7
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d

上記のコマンドは、リモートでマージおよび削除されたブランチをフェッチするために使用でき、リモートで使用できなくなったローカルブランチを削除します


これまでのところ最善の解決策ですが、grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -Dすべてを強制的に削除するように変更しました
Shoaib

ブランチ名のいずれかに部分文字列が含まれていると危険ですgone(例:)usingonefunction
Toby Speight

7

これのどれも私にとって本当に適切でした。originリモートブランチが削除された(gone)で、リモートブランチを追跡しているすべてのローカルブランチをパージするものが必要でした。リモートブランチを追跡するように設定されていないローカルブランチ(つまり、私のローカル開発ブランチ)を削除したくありませんでした。またgit、カスタムスクリプトを作成するのではなく、やその他のシンプルなCLIツールを使用するシンプルなワンライナーも欲しかった。最終的にはgrep、とawkを使用して、この単純なコマンドを作成しました。

これは最終的に私に終わったもの~/.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'

注:configコマンドでは、実際の構成と同じように、ではなく-dへのオプションを使用しています。マージされていないブランチについてGitが文句を言うのを聞きたくないので使用します。この機能も必要になる場合があります。その場合は、configコマンドの最後にではなく、単にを使用してください。git branch-D-D-D-d


gitエイリアスアプローチが好きです。簡単な質問:なぜやっgit branch -vvとのためにgreping : gone]としないgit branch -vためとgrep [gone]
lalibi

@lalibi、いい質問です。覚えていません。1つだけでは何かが表示されなかったのではないかと思いvます。場合はgit branch -v | grep '[gone]'あなたのために働く、それのために行きます。少しきれいに見えます。
Karl Wilbur

4

基づいて削除古いローカルブランチ:Gitのヒント、のようになりますjason.rickmanのソリューション私が呼ばれ、この目的のためにカスタムコマンドを実装gitのなくなっバッシュを使用して:

$ git gone
usage: git gone [-pndD] [<branch>=origin]
OPTIONS
  -p  prune remote branch
  -n  dry run: list the gone branches
  -d  delete the gone branches
  -D  delete the gone branches forcefully

EXAMPLES
git gone -pn    prune and dry run
git gone -d     delete the gone branches

git gone -pn 枝刈りと「なくなった」ブランチのリストを組み合わせます。

$ git gone -pn
  bport/fix-server-broadcast         b472d5d2b [origin/bport/fix-server-broadcast: gone] Bump modules
  fport/rangepos                     45c857d15 [origin/fport/rangepos: gone] Bump modules

次に、git gone -dまたはを使用してトリガーを引きますgit gone -D

ノート

  • 私が使用した正規表現は"$BRANCH/.*: gone]"$BRANCH通常の場所originです。Git出力がフランス語などにローカライズされている場合、これはおそらく機能しません。
  • Sebastian WiesnerはWindowsユーザー向けにRustにも移植しました。これはgit goneとも呼ばれます

これはおそらく受け入れられる答えになるはずです。OPの問題を解決git goneするのエイリアスのように見えgit branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -dます。
アレックス、

4

ここ他の多く 回答から大きく引き出されて、私は次のようになりました(git 2.13以上のみ、私は信じています)。これは、UNIXのようなシェルで動作するはずです。

git for-each-ref --shell --format='ref=%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)' refs/heads | while read entry; do eval "$entry"; [ ! -z "$ref" ] && git update-ref -d "$ref" && echo "deleted $ref"; done

これは特に(機械処理ではなく人間が読み取れる出力用に設計された「磁器」コマンドのように)のfor-each-ref代わりに使用し、その引数を使用して適切にエスケープされた出力を取得します(これにより、参照名の文字を気にする必要がなくなります)。branchbranch--shell


それは私にとってはうまくいきますが、コマンドの他のステップが何をしているのかを説明できればすばらしいでしょう。たとえば、私はどういう[ ! -z "$ref" ]意味かわかりません。マルチライナーはもう役に立ったと思います。しかし、まだあなたの入力をありがとう!
KevinH

4

さらに別の答えは、優雅さとクロスプラットフォーム性に対する私のニーズに合ったソリューションがないためです。

リモート上にないローカルブランチを削除するコマンド:

for b in $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads); do git branch -d $b; done

gitconfigと統合して、次のコマンドで実行できるようにしますgit branch-prune

バッシュ

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format='\''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'\'' refs/heads); do git branch -d $b; done'

パワーシェル

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format=''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'' refs/heads); do git branch -d $b; done'

(PowerShellとbashのユニバーサルコマンドを見つけるにはヘルプが必要です)

なぜこの答えが一番良いのですか?

  • 完全なソリューションを提供:git branch-pruneコマンドをgitに追加します
  • Windows PowerShellから正常に動作します
  • 核となるアイデアはあるjason.rickman @ s「は防弾方法使用しますgit for-each-ref
  • 解析とフィルタリングが行われる--filterため、外部の依存関係は必要ありません

説明:

  • 新しいエイリアスをに追加します~\.gitconfig。これを実行した後、あなたは単に行うことができますgit branch-prune
  • このエイリアスの内部:
    • ブランチをフェッチします --prune「リモート追跡ブランチをもうリモート上でプルーニングしない」フラグの
    • とを使用git for-each-refして--filter、ブランチのリストを取得します[gone](リモートなし)。
    • このリストをループして、ブランチを安全に削除します

1
@ jerry-wu氏、このソリューションの素晴らしいものを無限に改善してくれてありがとう。
氷村

@ jerry-wuと最後のgit configコマンドの編集はPowerShellでは機能しません((
Himura

1

私はこのbashスクリプトを思いつきました。それは、常に支店を維持しdevelopqamaster

git-clear() {
  git pull -a > /dev/null

  local branches=$(git branch --merged | grep -v 'develop' | grep -v 'master' | grep -v 'qa' | sed 's/^\s*//')
  branches=(${branches//;/ })

  if [ -z $branches ]; then
    echo 'No branches to delete...'
    return;
  fi

  echo $branches

  echo 'Do you want to delete these merged branches? (y/n)'
  read yn
  case $yn in
      [^Yy]* ) return;;
  esac

  echo 'Deleting...'

  git remote prune origin
  echo $branches | xargs git branch -d
  git branch -vv
}

1

私はトリックを行うために短い方法を使用します、それはいくつかの時間を節約し、より多くの可視性を与えることができるので、同じことをすることをお勧めします

次のスニペットを.bashrc(macosでは.bashprofile)に追加するだけです。

git-cleaner() { git fetch --all --prune && git branch --merged | grep -v -E "\bmaster|preprod|dmz\b" | xargs -n 1 git branch -d ;};
  1. すべてのリモコンを取得
  2. gitからマージされたブランチのみを取得
  3. このリストから「保護された/重要な」ブランチを削除します
  4. 残りを削除します(例:クリーンでマージされたブランチ)

必要に応じて、grep regexを編集する必要があります(ここでは、master、preprod、およびdmzが削除されないようにしています)


git fetch --all --pruneトリックをしました。ありがとう!
LeOn-Han Li、

1

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

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

ああ、私はこれを二重に投稿しました...投稿をレビューするときにこれを見ただけです。しかし、あなたはこれをあなたのものとする代わりに、このコマンドを提供した人を実際に指すことができます!
Dwza

私はフォーラムからそれを取得します。賢くなろうとせず、ただ答えを取るか無視してください
Fareed Alnamrouti

とにかく...とにかく...これについてあなたと話し合うためにここに来たのではありません。あなたが言ったように..。私のコメントを取るか無視してください;)
Dwza

0

どれくらいかはわかりませんが、今はgit-upを使用しています。

私がやるgit upと、それは新しい枝を追跡するために開始され、古いものを削除します。

明確にするために、これは標準のgitコマンドではありません— https://github.com/aanand/git-up

ところで、それはまた、ダーティツリーを隠し、リベースをそのままでリベースしますgit up

それが誰かのために役立つことを願っています


2
これは、サーバーに存在しないローカルブランチを削除するものではありません。
アシュリー

0

これが私が魚の殻に使う解決策です。上でテストMac OS X 10.11.5fish 2.3.0およびgit 2.8.3

function git_clean_branches
  set base_branch develop

  # work from our base branch
  git checkout $base_branch

  # remove local tracking branches where the remote branch is gone
  git fetch -p

  # find all local branches that have been merged into the base branch
  # and delete any without a corresponding remote branch
  set local
  for f in (git branch --merged $base_branch | grep -v "\(master\|$base_branch\|\*\)" | awk '/\s*\w*\s*/ {print $1}')
    set local $local $f
  end

  set remote
  for f in (git branch -r | xargs basename)
    set remote $remote $f
  end

  for f in $local
    echo $remote | grep --quiet "\s$f\s"
    if [ $status -gt 0 ]
      git branch -d $f
    end
  end
end

いくつかのメモ:

正しいを設定してくださいbase_branch。この場合develop、ベースブランチとして使用しますが、何でもかまいません。

この部分は非常に重要ですgrep -v "\(master\|$base_branch\|\*\)"。マスターやベースブランチを削除しないようにします。

git branch -d <branch>アップストリームまたは現在のHEADと完全にマージされていないブランチを削除しないように、私は追加の予防策として使用します。

テストする簡単な方法は、で置き換えるgit branch -d $fことecho "will delete $f"です。

私も追加する必要があると思います:自分のリスクで使用してください!


0

GitPythonを使用して、リモートに存在しないローカルブランチを削除するPythonスクリプトを記述しました。

    import git
    import subprocess
    from git.exc import GitCommandError
    import os

    def delete_merged_branches():
        current_dir = input("Enter repository directory:")
        repo = git.Repo(current_dir)
        git_command = git.Git(current_dir)

        # fetch the remote with prune, this will delete the remote references in local.
        for remote in repo.remotes:
            remote.fetch(prune=True)

        local_branches = [branch.name for branch in repo.branches]
        deleted_branches = []

        # deleted_branches are the branches which are deleted on remote but exists on local.
        for branch in local_branches:
            try:
                remote_name = 'origin/'+ branch
                repo.git.checkout(remote_name)
            except GitCommandError:
            # if the remote reference is not present, it means the branch is deleted on remote.
                deleted_branches.append(branch)

        for branch in deleted_branches:
            print("Deleting branch:"+branch)
            git_command.execute(["git", "branch", "-D",branch])


        # clean up the work flow.
        repo.git.checkout('master')
        repo.git.pull()

    if __name__ == '__main__':
        delete_merged_branches()

誰かが役に立てば幸いです。何か見逃した場合はコメントを追加してください。


0

インストール済みのzshシェルを使用してOh My Zshいる場合、これを安全に行う最も簡単な方法は、組み込みのオートコンプリートを使用することです。

まず、削除するブランチを決定します。

~ git branch --merged

  branch1
  branch2
  branch3
* master

これにより、すでにマージされたブランチのリストが表示されます

削除したいものがいくつかわかったら、次のように入力します。

~ git branch -d 

あなたがしなければならないすべては[タブ]を押すことであり、それはあなたにローカルブランチのリストを表示します。タブ補完を使用するか、もう一度[タブ]を押すだけで、[Enter]でブランチを選択できます。

Tab削除するブランチのリストが表示されるまで、ブランチを繰り返し選択します。

~ git branch -d branch1 branch2 branch3

次に、Enterキーを押してブランチのコレクションを削除します。

端末でzshを使用していない場合は、こちらから入手してください。


0

コマンドを読みやすくするため、パイプを使用するのが好きです。

これは、master以外のすべてのブランチを削除する場合の私の解決策です。

git branch | grep -v master | xargs -n 1 git branch -D

基準に一致する他のブランチを削除するには、最初と2番目のブロックを変更します。

git branch --merged | grep feature_name | xargs -n 1 git branch -D

-3

gitクライアントを使用して私のために働いた簡単な答えは次のとおりです:

リポジトリをマシンから完全に削除して、もう一度チェックアウトします。

危険なスクリプトをいじる必要はありません。


2
現在取り組んでいるブランチについてはどうですか:/
MailoSvětel'16

@MailoSvětelがリモートにある場合は、もう一度プルすることができます(コミットして、最新の作業をリモートにプッシュすることを忘れないでください)
Juan Carlos Ospina Gonzalez

私の質問とほとんどの回答では、不要な作業を回避しようとしています。言い換えれば、私がしなければならないのは、ブランチを削除することだけであり、もう作業しません。repoを削除し、それを複製してブランチの追跡を再開するのは、私にとって不必要な作業の多くです。その上、いくつかの作業は失われる可能性があります:(
MailoSvětelSep
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.