2013-11-20 4 views
200

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

Почему?

+0

'мерзавец ветвь -d the_local_branch' – krsteeve

+0

Спасибо, но я просто любопытно, почему это могло произойти. – gogogadgetinternet

+0

Существовала тонкая разница при работе с иерархией ветвей ('x/y'): она была исправлена ​​(см. [Мой ответ ниже] (http://stackoverflow.com/a/21072934/6309)) – VonC

ответ

383

Я не обвиняю вас в том, что вы разочарованы этим. Это лучший способ взглянуть на это. Есть потенциально три версии каждого удаленного филиала:

  1. Фактический филиал на удаленном хранилище
  2. Ваш снимок этой ветви локально (хранится под refs/remotes/...)
  3. и местного отделения, которые могут быть отслеживающие пульт Отделение

Начнем с git prune. Это удаляет объектов, которые больше не ссылаются, а не ссылки. В вашем случае у вас есть локальный филиал. Это означает, что есть ссылка с именем random_branch_I_want_deleted, которая относится к некоторым объектам, которые представляют историю этой ветви. Итак, по определению git prune не удалит random_branch_I_want_deleted. Это действительно способ удалить данные, накопленные в Git, но на них не ссылаются ни на что полезное. В общем, это не влияет на ваш взгляд на какие-либо отрасли.

git remote prune origin и git fetch --prune оба действуют по ссылкам ниже refs/remotes/... (я буду называть их удаленными ссылками). Это не влияет на местные филиалы. Версия git remote полезна, если вы хотите удалить удаленные ссылки под конкретным пультом дистанционного управления. В противном случае они делают то же самое. Итак, короче говоря, git remote prune и git fetch --prune работают над номером 2 выше.

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

+8

Это лучше справляется с общим вопросом, объясняя соответствующие различия. Он также отвечает на дополнительные вопросы, которые я получил от вышеприведенного. – gogogadgetinternet

+10

Эта команда покажет список всех локальных ветвей, которые не имеют соответствующей удаленной ветви. Вы _could_ передаете это в 'xargs git branch -D', но обратите внимание, что любые новые ветви, которые вы создали, но никогда не нажатые на сервер, будут удалены, поэтому тщательно протестируйте: ' git branch -r | awk '{print $ 1}' | egrep -v -f/dev/fd/0 <(ветвь git -vv | grep origin) | awk '{print $ 1}' ' –

+0

Отличный ответ, оцените обзор удаленных ветвей« версии » – Noel

35

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

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

git branch -d random_branch_I_want_deleted 

Заменить -d на -D, если ветвь не объединены в других

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

+1

Я знаю это кажется очевидным, но 'git prune' выглядит не только для филиалов и тегов, но и для всех других ссылок. – hvd

+0

Итак, в моем случае, почему бы не порезать работу? Потому что это не касается местных филиалов, а удаленных ссылок?Спасибо за краткую информацию. – gogogadgetinternet

+0

@hvd Какие существуют ссылки, кроме ветвей и тегов? – CharlesB

10

Обратите внимание, что одна разница между git remote --prune и git fetch --prune будет закреплен, с commit 10a6cc8, по Tom Miller (tmiller) (для мерзавца 1,9/2,0, Q1 2014):

Когда мы дистанционно отслеживать филиал под названием «frotz/nitfol» из предыдущей выборки, , и у восходящего потока теперь есть ветвь с именем «** frotz» **, fetch не удалил бы «frotz/nitfol» с «git fetch --prune» из восходящего потока.
git сообщит пользователю, что «git remote prune» устранит проблему.

Итак: когда upstream repo имеет филиал («frotz») с тем же именем, что и branch hierarchy («frotz/ххх», возможный branch naming convention), git remote --prune был успех (в очистке удаленная ветка отслеживания от вашего репо), но git fetch --prune не прошел.

Не больше:

Изменить путь «fetch --prune» работает путем перемещения операции обрезки до кокетливой операции.
Таким образом, вместо того, чтобы предупреждать пользователя о конфликте, он автоматически исправляет его.

8

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

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

сохранить его в файле с именем git-rm-ntb (назовем его что угодно) на PATH и запуск:

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

clean() 
{ 
    REMOTES="[email protected]"; 
    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 [email protected] 
+0

Спасибо! Хорошее прикосновение с цветным выходом ;-) – BVengerov