web-dev-qa-db-ja.com

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

私の状況はこれです...同じレポに取り組んでいる誰かが彼のローカルとリモートのレポからブランチを削除しました...

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':というタイトルのセクションにのみあることに注意してください。

どうして?

297

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

  1. リモートリポジトリ上の実際のブランチ
    (例: https://example.com/repo.gitrefs/heads/masterのリモートレポジトリ)
  2. そのブランチのあなたのスナップショットをローカルに(refs/remotes/...の下に保存されています)
    (例:地方レポ、refs/remotes/Origin/master
  3. そして、リモートブランチを追跡している可能性があるローカルブランチ
    (例:地方レポ、refs/heads/master

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

git remote Prune Origingit fetch --Pruneはどちらもrefs/remotes/...の下の参照を操作します(これらをリモート参照と呼びます)。地元の支店には影響しません。 git remoteバージョンは、特定のリモートの下にあるリモート参照だけを削除したい場合に便利です。そうでなければ、2つはまったく同じことをします。つまり、git remote Prunegit fetch --Pruneは上記の番号2を処理します。たとえば、git Web GUIを使用してブランチを削除し、それをローカルのブランチリスト(git branch -r)に表示したくない場合は、これが使用するコマンドです。

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

554

git remote Prunegit fetch --Pruneは同じことをします:あなたが言ったように、リモートに存在しないブランチへの参照を削除します。 2番目のコマンドはリモートに接続し、整理の前に現在のブランチを取得します。

しかしそれはあなたがチェックアウトしたローカルブランチには影響しません。

git branch -d  random_branch_I_want_deleted

ブランチが他の場所にマージされていない場合は、-d-Dに置き換えます。

git Pruneは何か別のことをします、それは到達不可能なオブジェクト、どのブランチやタグでも到達できないコミット、そしてもはや必要とされないコミットを削除します。

49
CharlesB

git remote --Prunegit fetch --Pruneの違いの1つが修正されており、 commit 10a6cc8Tom Miller(tmiller (git 1.9/2.0、Q1の場合) 2014):

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

そのため:アップストリームリポジトリに、ブランチ階層と同じ名前のブランチ( "frotz")がある場合(「frotz/xxx」、可能な ブランチの命名規則 )、git remote --Pruneは成功しました(リポジトリからリモートトラッキングブランチをクリーンアップする際に)が、git fetch --Pruneは失敗しました。

もう違います:

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

13
VonC

誰かが興味を持っているだろうというイベントでは。これは、リモートで追跡されていないすべてのローカルブランチを削除する簡単なシェルスクリプトです。警告の言葉:これは、マージされたかどうかにかかわらず、リモートで追跡されていないブランチを取り除きます。

あなたがこれに関する何か問題を見たならば、私に知らせてください、そして、私はそれを修正します(など)。

PATH上のgit-rm-ntbという名前のファイルに保存して(なんでも呼び出してください)、次のコマンドを実行します。

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 $@
10
D.Mill