古いリモートgitブランチをクリーンアップする


694

私は2つの異なるコンピューター(AとB)で作業し、共通のgitリモートをドロップボックスディレクトリに保存しています。

マスターと開発の2つのブランチがあるとします。どちらも、リモートの相手のorigin / masterおよびorigin / develを追跡しています。

次に、コンピューターAで、ローカルとリモートのブランチ開発を削除します。

git push origin :heads/devel
git branch -d devel

git branch -aコンピューターAで実行すると、次のブランチのリストが表示されます。

  • 主人
  • origin / HEAD
  • 起源/マスター

git fetchコンピューターBで実行している場合、でローカルの開発ブランチをgit branch -d devel削除できますが、リモートの開発ブランチは削除できません。

git push origin :heads/devel 次のエラーメッセージを返します。

エラー:修飾されていない宛先に転送できません:heads / proxy3d
宛先のrefspecがリモートの既存の参照と一致しないか、refs /で始まっていません。また、ソースの参照に基づいてプレフィックスを推測できません。
致命的:リモートエンドが突然ハングアップした

git branch -a まだリモートブランチのorigin / develをリストしています。

コンピューターBからリモートブランチをクリーンアップするにはどうすればよいですか?


4
Dropboxフォルダーのgitリポジトリは少し壊れやすい(ただし、追加の詳細はありません)と聞いたことがあります。
–ThorbjørnRavn Andersen 2013

5
@ThorbjørnRavnAndersenおそらく、コミットするたびに完全に同期されるのを待たなければならないため、他のマシンで安全に使用できることが確認できます(それでも、別の同期が必要です)。
ataulm 2013

回答:


1239

まず、git branch -aマシンBでの結果は何ですか?

次に、ですでに削除されheads/develているoriginため、マシンBから削除できません。

試す

git branch -r -d origin/devel

または

git remote prune origin

または

git fetch origin --prune

ステートメント--dry-runの最後に追加して、git実際に実行せずに実行した結果を確認してください。

git remote pruneおよびのドキュメントgit branch


50
git remote prune origin私のために働いた=> * [pruned] origin/my-old-branch
Hari Karam Singh

126
git remote prune origin --dry-run実際に削除しないと何が削除されるかを示します。
Wolfram Arnold

30
git fetch origin --prune削除されたブランチを削除するのに最適でした
セバスチャンバルビエリ

10
なくなったリモートを追跡するローカルブランチがある場合、これは何も削除しません。それらについては、それが表示git branch -vvされgit branch -D branchname、最後にプルーンが最善の方法です。
Roman Starkov 14年

7
あなたは次のオプションを設定することにより、フェッチ/プルで自動的に発生する剪定設定することができます:git config remote.origin.prune true
パトリック・ジェームズMcDougle

99

実行することを検討してください:

git fetch --prune

各リポジトリで定期的に、削除されたリモートブランチを追跡していたローカルブランチを削除します(リモートGITリポジトリには存在しません)。

これはさらに簡略化できます

git config remote.origin.prune true

これは、per-repo将来git fetch or git pull自動的にプルーニングする設定です。

これをユーザー用に設定するには、グローバル.gitconfigを編集して追加することもできます

[fetch]
    prune = true

ただし、これは次のコマンドを使用して行うことをお勧めします。

git config --global fetch.prune true

またはそれをシステム全体に適用する(ユーザーだけでなく)

git config --system fetch.prune true

14

これがあなたのためにできるbashスクリプトです。これは、http://snippets.freerobby.com/post/491644841/remove-merged-branches-in-gitスクリプトの修正バージョンです。私の変更により、さまざまなリモートロケーションをサポートできるようになりました。

#!/bin/bash

current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
if [ "$current_branch" != "master" ]; then
  echo "WARNING: You are on branch $current_branch, NOT master."
fi
echo -e "Fetching merged branches...\n"

git remote update --prune
remote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")
local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")
if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
  echo "No existing branches have been merged into $current_branch."
else
  echo "This will remove the following branches:"
  if [ -n "$remote_branches" ]; then
echo "$remote_branches"
  fi
  if [ -n "$local_branches" ]; then
echo "$local_branches"
  fi
  read -p "Continue? (y/n): " -n 1 choice
  echo
  if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
    remotes=`echo "$remote_branches" | sed 's/\(.*\)\/\(.*\)/\1/g' | sort -u`
# Remove remote branches
for remote in $remotes
do
        branches=`echo "$remote_branches" | grep "$remote/" | sed 's/\(.*\)\/\(.*\)/:\2 /g' | tr -d '\n'`
        git push $remote $branches 
done

# Remove local branches
git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
  else
echo "No branches removed."
  fi
fi

1
これは、「origin / feature / mybranch」というブランチで壊れました。理由はわかりません。
Stavros Korokithakis 2014年

問題は2つにありsedます。置き換えsed 's/\(.*\)\/\(.*\)/\1/g'によってsed 's/\([^/]*\)\/\(.*\)/\1/g'
ブノワ・Latinier

14

このコマンドはorigin、を除いて、すべてのリモート()マージ済みブランチを「ドライラン」で削除しmasterます。これを変更するか、マスターの後にブランチを追加できます。grep -v for-example-your-branch-here |

git branch -r --merged | 
  grep origin | 
  grep -v '>' | 
  grep -v master | 
  xargs -L1 | 
  awk '{sub(/origin\//,"");print}'| 
  xargs git push origin --delete --dry-run

見た目が良ければ、を取り外します--dry-run。さらに、これを最初にフォークでテストすることもできます。


いいね。1番目のxargs + awkの代わりにperlを使用した私の微調整:git branch -r --merged | grep origin | grep -v '>' | grep -vマスター| perl -lpe '($ junk、$ _)= split(/ \ //、$ _、2)' | xargs git push origin --delete
Andrew

6

場合git branch -rのショーあなたに興味を持っていないと、あなただけのローカルからそれらを削除することをリモート追跡の枝の多くは、次のコマンドを使用します。

git branch -r | grep -Ev 'HEAD|master|develop'  | xargs -r git branch -rd

より安全なバージョンは、マージされたものだけを削除することです:

git branch -r --merged | grep -Ev 'HEAD|master|develop'  | xargs -r git branch -rd

これは、他のチームメイトの機能ブランチは必要ないが、最初のクローンでフェッチされた多くのリモート追跡ブランチがある大規模なプロジェクトに役立つ場合があります。

ただし、この手順だけでは不十分git fetchです。削除されたリモート追跡ブランチが次に戻るためです。

これらのリモート追跡ブランチのフェッチを停止するには、フェッチする参照を.git / configに明示的に指定する必要があります。

[remote "origin"]
  # fetch = +refs/heads/*:refs/remotes/origin/*    ### don't fetch everything
  fetch = +refs/heads/master:refs/remotes/origin/master
  fetch = +refs/heads/develop:refs/remotes/origin/develop
  fetch = +refs/heads/release/*:refs/remotes/origin/release/*

上記の例ではmaster、ブランチのフェッチdevelopリリースのみを行っており、必要に応じて自由に変更できます。


1
おかげで、最初のコマンドがうまくいきました。また、現在のブランチ(私の個人的なお気に入り)のみをフェッチするgit fetch origin branchnameようなエイリアスを作成して、ブランチを1つだけフェッチすることもできますft = "!f() { git fetch origin $(git rev-parse --abbrev-ref HEAD);}; f"。乾杯。
GiovanyMoreno

多分OTですが、-rフラグは何を意味していますか?議論があるようですxargsが、-Rについて何も見つかりませんでした-r。つまり、理論的には、正しく機能してxargsいることを覚えていれば、機能しなく-rても機能するはずです。
アルド 'xoen' Giambelluca

私はこの答えが好きです。いくつかの注意事項(明らかなことを実際に述べている)。最後のパイプと最後のコマンドを削除することで、どのブランチが削除されるかを「プレビュー」することができ| xargs git branch -dます。また、-rオプション(--remotes)を削除することによりgit branch -d、ローカルブランチのみをクリーンアップします(デフォルトでgit branchはリモートブランチが表示されないことを考慮すれば十分です)。
Aldo 'xoen' Giambelluca

ありがとう!これはまさに私が必要としたものでした。他の解決策では、枝刈りされたローカルブランチをリモートにプッシュしてそこから削除することも提案されていますが、リモートが削除されているか存在しない場合は役に立ちません。このアプローチにより、アクセスできなくなったリモートブランチへのローカル参照が削除されました。
cautionbug

@aldo、xargs -rつまり、つまり--no-run-if-empty、これはGNU拡張機能であることを意味します。これは素晴らしい説明です。
ryenus

4

削除は常にやりがいのある作業であり、危険な場合があります !!! したがって、まず次のコマンドを実行して何が起こるかを確認します。

git push --all --prune --dry-run

上記のようにgitすると、以下のコマンドを実行するとどうなるかが一覧表示されます。

次に、次のコマンドを実行して、ローカルリポジトリにないすべてのブランチをリモートリポジトリから削除します。

git push --all --prune

10
このコマンドは危険なようです...それは私が欲しかったものを削除することができました(そして上記の答えのうち少なくとも4つではできませんでした)。ただし、他の4つの開発ブランチも削除されました。Gitは絶対に
最悪

2
これらのブランチは、ローカルに存在していない必要があります。しかし、すべてが失われるわけではありません。Git commit、Git reflog、次にgit reset --hard <checksum>。これを使用すると、文字通り、任意のコミット(別名:保存)および他の人にコミットできます。ブランチは単なるラベルです。ラベルを削除しても保存は削除されません...チェックサムは永久に残ります。お手伝いできるかどうかお知らせください
ティモシーLJスチュワート

3
もちろん、gitのガベージコレクターは最終的にブランチによって参照されていないコミットを削除するため、これらをかなり迅速に回復する必要があります。
Andrew

1
-nこのコマンドに(ドライラン)を追加して、変更をプレビューし、問題がなければ、なしでもう一度呼び出すと便利です-n
mati865 2016

1
@GuiWeinmannに同意する-これは、特に最初に予行演習でこれを実行するための特定の呼び出しがないと、危険すぎます。
Vivek M. Chawla 2017年

2

SourceTree(v2.3.1)でこれを行う方法は次のとおり
です。1. [フェッチ]をクリックします
2. [ トラッキングブランチを 削除...]をオンにし
ます3. OKを押します
4.😀

ここに画像の説明を入力してください


1

他の回答は私のケースをカバーしていないか、不必要に複雑なため、ここに回答を追加する必要があります。私は他の開発者と一緒にgithubを使用していますが、github PRからリモートが(おそらくマージされて)削除されたすべてのローカルブランチを私のマシンから一度に削除したいと思っています。いいえ、git branch -r --mergedローカルでマージされなかったブランチや、まったくマージされなかった(放棄された)ブランチなどは対象外なので、別のソリューションが必要です。

とにかく、私は他の答えからそれを得た最初のステップ:

git fetch --prune

git remote prune originドライランは私の場合も同じことをするように見えたので、私はそれを単純に保つために最短バージョンを使いました。

これで、git branch -vは、リモートが削除されたブランチをとしてマークする必要があり[gone]ます。したがって、私がしなければならないすべては次のとおりです。

git branch -v|grep \\[gone\\]|awk '{print $1}'|xargs -I{} git branch -D {}

それと同じくらい簡単で、上記のシナリオで必要なすべてが削除されます。

あまり一般的でないxargs構文は、Linuxに加えてMacとBSDでも機能するようにするためです。注意、このコマンドは予行演習ではないため、とマークされたすべてのブランチを強制削除し[gone]ます。明らかに、これはgitであることは永遠に消えることはありません。削除したいブランチを見つけた場合、いつでも元に戻すことができます(上記のコマンドでは、削除時にハッシュがリストされるため、単純git checkout -b <branch> <hash>です。


0
# First use prune --dry-run to filter+delete the local branches
git remote prune origin --dry-run \
  | grep origin/ \
  | sed 's,.*origin/,,g' \
  | xargs git branch -D

# Second delete the remote refs without --dry-run
git remote prune origin

local-とremote-refs(私の例ではorigin)から同じブランチをプルーニングします。

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