git remote prune、git prune、git fetch --pruneなどの違いは何ですか?


358

私の状況はこれです...同じリポジトリで作業している誰かがローカルとリモートのリポジトリからブランチを削除しました...

Stack Overflowや他のサイトでこの種の問題について質問したほとんどの人git branch -aは、下部のリモート追跡ブランチリストにブランチの問題がまだ表示されています。

* master
  develop
  feature_blah
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah
  remotes/origin/random_branch_I_want_deleted

しかし、私の状況では、そこにあるべきではないブランチはローカルです:

* master
  develop
  feature_blah
  random_branch_I_want_deleted
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah

次のいずれかを実行しても、ローカルで削除されません。

$ git prune

私も試しました:

$ git remote prune origin
$ git fetch --prune

より役立つ情報:チェックgit remote show originすると、次のようになります。

* remote origin
Fetch URL: utilities:homeconnections_ui.git
Push  URL: utilities:homeconnections_ui.git
HEAD branch: master
Remote branches:
 master                        tracked
 develop                       tracked
 feature_blah                  tracked
 other123                      tracked
 other444                      tracked
 other999                      tracked
Local branches configured for 'git pull':
 develop                      merges with remote develop
 feature_blah                 merges with remote other999
 master                       merges with remote master
 random_branch_I_want_deleted merges with remote random_branch_I_want_deleted
Local refs configured for 'git push':
 develop         pushes to develop     (local out of date)
 master          pushes to master      (up to date)
 feature_blah    pushes to feature_blah(up to date)

というタイトルのセクションにのみあることに注意してください Local branches configured for 'git pull':

どうして?


git branch -d the_local_branch
krsteeve 2013年

1
おかげで、なぜそれが起こったのか興味があります。
gogogadgetinternet 2013年

ブランチ階層(x/y)を扱うときに微妙な違いがありました:修正されました(以下の私の回答を参照しください)
VonC

回答:


664

このことに不満を抱いたとしても、私はあなたを責めません。見るための最良の方法はこれです。すべてのリモートブランチには、潜在的に3つのバージョンがあります。

  1. リモートリポジトリ上の実際の分岐
    (例えば、リモートレポでhttps://example.com/repo.gitrefs/heads/master
  2. ローカルにあるブランチのスナップショット(に保存refs/remotes/...
    (例:ローカルリポジトリrefs/remotes/origin/master
  3. そして、リモートブランチを追跡しているかもしれないローカルブランチ
    (例えば、ローカルリポジトリrefs/heads/master

から始めましょうgit prune。これにより、参照されなくなったオブジェクトは削除され、参照は削除されません。あなたの場合、あなたはローカルブランチを持っています。つまりrandom_branch_I_want_deleted、そのブランチの履歴を表すいくつかのオブジェクトを参照するという名前のrefがあるということです。したがって、定義により、git pruneは削除されませんrandom_branch_I_want_deleted。本当に、git pruneGitに蓄積されているが何からも参照されていないデータを削除する方法です。一般に、ブランチのビューには影響しません。

git remote prune originそして、git fetch --pruneの両方が下の参照を操作するrefs/remotes/...(私はリモート参照としてこれらを参照します)。ローカルブランチには影響しません。このgit remoteバージョンは、特定のリモートのリモート参照のみを削除する場合に役立ちます。それ以外の場合、2つはまったく同じことを行います。つまり、簡単に言うgit remote pruneと、git fetch --prune上記の2番を操作します。たとえば、git Web GUIを使用してブランチを削除し、それがローカルブランチリストに表示されないようにする場合(git branch -r)、これは使用するコマンドです。

ローカルブランチを削除するには、使用する必要がありますgit branch -d(または-D、どこにもマージされていない場合)。FWIW、リモートブランチが消えた場合にローカルトラッキングブランチを自動的に削除するgitコマンドはありません。


22
これは、適切な違いを説明することにより、全体的な質問に対処するためのより良い仕事をします。また、上記の質問からの追加の質問にも答えます。
gogogadgetinternet 2013年

14
このコマンドは、対応するリモートブランチがないすべてのローカルブランチのリストを表示します。あなたは可能性へのパイプこれをxargs git branch -D:しかし、あなたが作成したが、サーバーにプッシュたことがありません任意の新しい枝がそうトレッド慎重に、削除されることに注意してください git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}'
ジェイソン・ウォルトン

4
@シードいいえ、ありません。:-(ローカルのリモート追跡参照を削除するだけです。バージョン2.7.0でこれを再確認しました
John Szakmeister

1
@ BlueRaja-DannyPflughoeftそのアプローチには注意してください。たとえば、安定したブランチの実行方法によっては、それらがマスターブランチにマージされたように見え、最終的にそれらを削除することになります。サーバーからそれらを削除していないので、ここでは大きな損失ではありませんが、特別な構成を設定した場合、ブランチが削除されるとそれは失われます。
John Szakmeister 2017年

1
@Cloud完全に真実ではありません。参照はパックすることができます(領域内のpacked-refsファイルを参照.git)。そのため、ファイルエクスプローラーを使用して参照を削除することは必ずしも簡単ではありません。コマンドを使用して、両方が正しく処理されるようにすることをお勧めします。
John Szakmeister

55

git remote pruneそしてgit fetch --prune、あなたが言ったように、リモートに存在しない枝に引用文献を削除:同じことを行います。2番目のコマンドはリモートに接続し、プルーニングの前に現在のブランチをフェッチします。

ただし、チェックアウトしたローカルブランチには影響しません。

git branch -d  random_branch_I_want_deleted

交換する-dことにより、-D分岐が他の場所でマージされていない場合

git prune 何か違うことをします、それは到達不能なオブジェクト、どのブランチやタグでも到達できず、もはや必要とされないコミットをパージします。


1
私はそれが明白ようだが、知っているgit pruneだけではなく、ブランチやタグが、他のすべての参照文献にも探します。

だから私の場合、git pruneが機能しないのはなぜですか?それはローカルブランチではなくリモート参照を気にしないのですか?簡潔な情報をありがとう。
gogogadgetinternet 2013年

@hvdブランチとタグ以外にどんな種類の参照がありますか?
CharlesB 2013年

@gogogadgetinternetはい正確に。(あなたが意味したとしたらgit remote prune
CharlesB 2013年

4
IMOは、オブジェクトコレクション参照クリーンアップの両方に「プルーン」を使用するgitの命名規則ですが、混乱が生じます。しかし、それはgitにおける多くのUIパズルの1つにすぎません。:-)
torek 2013年

14

どなたでも興味を持っていただけると思います。リモートで追跡されていないすべてのローカルブランチを削除する簡単なシェルスクリプトを次に示します。注意:これは、マージされたかどうかに関係なく、リモートで追跡されていないすべてのブランチを削除します。

この問題が発生した場合はお知らせください。修正します(など)。

と呼ばれるファイルに保存し、git-rm-ntb(何でも呼び出す)PATHを実行します。

git-rm-ntb <remote1:optional> <remote2:optional> ...

clean()
{
  REMOTES="$@";
  if [ -z "$REMOTES" ]; then
    REMOTES=$(git remote);
  fi
  REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
  RBRANCHES=()
  while read REMOTE; do
    CURRBRANCHES=($(git ls-remote $REMOTE | awk '{print $2}' | grep 'refs/heads/' | sed 's:refs/heads/::'))
    RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
  done < <(echo "$REMOTES" )
  [[ $RBRANCHES ]] || exit
  LBRANCHES=($(git branch | sed 's:\*::' | awk '{print $1}'))
  for i in "${LBRANCHES[@]}"; do
    skip=
    for j in "${RBRANCHES[@]}"; do
      [[ $i == $j ]] && { skip=1; echo -e "\033[32m Keeping $i \033[0m"; break; }
    done
    [[ -n $skip ]] || { echo -e "\033[31m $(git branch -D $i) \033[0m"; }
  done
}

clean $@

ありがとう!色付きの出力で素敵なタッチ;-)
BVengerov

2
$(git branch -d $ i)はマージされたブランチのみを削除する方が安全ではないでしょうか?
user2012677

とても役に立ち、ありがとうございました!!!
ロビンハートランド

より安全なオプションについては、stackoverflow.com
questions / 7726949 /…

13

Tomミラー(によるコミット10a6cc8で、git remote --pruneと1つの違いgit fetch --pruneが修正されていることに注意してください(git 1.9 / 2. 0、2014年第1四半期の場合):tmiller

frotz/nitfol以前のフェッチから" " という名前のリモート追跡ブランチがあり、アップストリームに "** frotz " ** という名前のブランチfetchがある場合、アップストリームから" frotz/nitfol"を含む " git fetch --prune" を削除できませんでした。
gitは、ユーザーに「git remote prune」を使用して問題を修正するよう通知します。

したがって、上流のリポジトリにブランチ階層と同じ名前のブランチ( "frotz")がある場合( "frotz / xxx"、可能なブランチ命名規則)、git remote --prune(リモートトラッキングブランチをリポジトリからクリーンアップすることで)成功しました。 、しかしgit fetch --prune失敗していた。

もう違います:

fetch --pruneフェッチ操作の前にプルーニング操作を移動して、「」の動作を変更します。
このようにして、競合をユーザーに警告する代わりに、自動的に修正します。

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