Каковы различия между git remote prune, git prune, git fetch --prune и т. д

моя ситуация такова... кто-то, работающий над тем же РЕПО, удалил ветку из своего локального и удаленного РЕПО...

большинство людей, которые спрашивали об этой проблеме при переполнении стека или других сайтах, имеют проблему ветвей, все еще отображаемых в их списке ветвей удаленного отслеживания 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':

почему?

4 ответов


я не виню тебя за то, что ты расстраиваешься из-за этого. Лучший способ взглянуть на это. Существует потенциально три версии каждой удаленной ветви:

  1. фактическая ветвь на удаленном репозитории
  2. ваш снимок этой ветви локально (хранится под refs/remotes/...)
  3. и локальная ветвь, которая может отслеживать удаленную ветвь
С git prune. Это удаляет объекты что нет при более длительных ссылках ссылки не удаляются. В вашем случае, у вас есть местное отделение. Это означает, что есть рефери по имени random_branch_I_want_deleted это относится к некоторым объектам, которые представляют историю этой ветви. Итак, по определению,git prune не будут удалены random_branch_I_want_deleted. Действительно,git prune - это способ удалить данные, которые накопились в Git, но на которые ничего не ссылается. В общем, это не влияет на ваше представление о каких-либо ветвях.

git remote prune origin и git fetch --prune как работать на ссылки в разделе refs/remotes/... (Я буду ссылаться на них как на удаленные ссылки). Это не влияет на местные филиалы. The git remote версия полезна, если вы хотите удалить удаленные ссылки под конкретный пульт. В противном случае они делают одно и то же. Короче говоря,git remote prune и git fetch --prune работайте на номере 2 выше. Например, если вы удалили ветку с помощью Git web GUI и больше не хотите, чтобы она отображалась в вашем локальном списке ветвей (git branch -r), тогда это команда, которую вы должны использовать.

чтобы удалить локальную ветку, нужно использовать git branch -d (или -D если он нигде не объединен). FWIW, нет команды git для автоматического удаления локальных ветвей отслеживания, если удаленная ветвь исчезает.


git remote prune и git fetch --prune сделайте то же самое: удалите ссылки на ветви, которые не существуют на пульте дистанционного управления, как вы сказали. Вторая команда подключается к удаленному и извлекает его текущие ветви перед обрезкой.

однако он не касается локальных ветвей, которые вы проверили, что вы можете просто удалить с

git branch -d  random_branch_I_want_deleted

заменить -d by -D если ветвь не объединена в другом месте

git prune делает что-то другое, он очищает недостижимые объекты, те коммиты, которые недоступны ни в одной ветке или теге и, следовательно, больше не нужны.


обратите внимание, что единственное различие между git remote --prune и git fetch --prune фиксируется, с совершить 10a6cc8, by Тома Миллера (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" работает перемещая операцию обрезки перед операцией выборки.
Таким образом, вместо предупреждения пользователя о конфликте он автоматически исправляет его.


в случае, если кто-то будет заинтересован. Вот быстрый сценарий оболочки, который удалит все локальные ветви, которые не отслеживаются удаленно. Предупреждение: это избавит от любой ветви, которая не отслеживается удаленно, независимо от того, была ли она объединена или нет.

если вы видите какие-либо проблемы с этим, пожалуйста, дайте мне знать, и я буду это исправить (и т. д. так далее.)

сохранить его в файле с именем 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 }' | grep 'refs/heads/' | sed 's:refs/heads/::'))
    RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
  done < <(echo "$REMOTES" )
  [[ $RBRANCHES ]] || exit
  LBRANCHES=($(git branch | sed 's:\*::' | awk '{print }'))
  for i in "${LBRANCHES[@]}"; do
    skip=
    for j in "${RBRANCHES[@]}"; do
      [[ $i == $j ]] && { skip=1; echo -e "3[32m Keeping $i 3[0m"; break; }
    done
    [[ -n $skip ]] || { echo -e "3[31m $(git branch -D $i) 3[0m"; }
  done
}

clean $@