Quais são as diferenças entre o Git remoto prune, git prune, git fetch --prune, etc

A minha situação é esta... alguém que trabalha no mesmo repo apagou um ramo do seu repo local e remoto...

a maioria das pessoas que perguntaram sobre este tipo de problema no fluxo de pilha, ou outros sites têm a questão de ramos ainda mostrando em sua lista de ramificações de rastreamento remoto git branch -a No fundo:

* master
  develop
  feature_blah
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah
  remotes/origin/random_branch_I_want_deleted
No entanto, na minha situação, o ramo que não devia estar lá, é local.
* master
  develop
  feature_blah
  random_branch_I_want_deleted
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah
Quando faço alguma coisa a seguir, não é removida. localmente:

$ git prune

também tentei:

$ git remote prune origin
$ git fetch --prune

informação mais útil: quando eu verificar git remote show origin isto é o que parece:

* 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)
Repara que só está na secção intitulada Local branches configured for 'git pull':

Porquê?

Author: Matthew Rankin, 2013-11-21

4 answers

Não te culpo por ficares frustrado com isto. A melhor maneira de ver é esta. Existem potencialmente três versões de cada ramificação remota:
  1. a sucursal real no repositório remoto
  2. a sua imagem desse ramo localmente (guardada em refs/remotes/...)
  3. E um ramo local que pode estar a seguir o ramo remoto.
Vamos começar por ... Isto remove objectos que já não estão a ser referenciados, não remover as referências. No seu caso, tem uma filial local. Isso significa que há um árbitro chamado random_branch_I_want_deleted que se refere a alguns objetos que representam a história desse ramo. Então, por definição, git prune não irá remover random_branch_I_want_deleted. Realmente, git prune é uma maneira de apagar dados que se acumularam no Git, mas que não estão a ser referenciados por nada. Em geral, não afecta a sua visão de nenhum ramo.

git remote prune origin e {[7] } ambos operam com referências em {[[0]} (vou referir-me a estas como referências remotas). Ele não afecta os ramos locais. A versão git remote é útil se você só quiser remover as referências remotas sob um remoto em particular. Caso contrário, os dois fazem exactamente a mesma coisa. Então, em resumo, git remote prune e git fetch --prune operam no número 2 acima. Por exemplo, se você excluir uma ramificação usando a GUI web do git e não quiser que ela apareça mais na sua lista de ramificações local (git branch -r), então este é o comando que você deve usar.

Para remover um ramo local, deve usar git branch -d (ou -D Se não for fundiu-se em qualquer lugar). FWIW, não existe nenhum comando git para remover automaticamente os ramos de rastreamento locais se um ramo remoto desaparecer.

 465
Author: John Szakmeister, 2018-07-03 20:11:57

git remote prune e git fetch --prune faz a mesma coisa: apagar os árbitros para os ramos que não existem no remoto, como disseste. O segundo comando conecta-se ao remoto e pega seus ramos atuais antes da poda.

No entanto, não toca nos ramos locais que você verificou, que você pode simplesmente apagar com {[[8]}

git branch -d  random_branch_I_want_deleted

Substituir -d por -D se o ramo não estiver reunido noutro lado

git prune faz alguma coisa diferente, purgaobjectos inacessíveis, aqueles commits que não são alcançáveis em nenhum branch ou tag, e assim não precisa mais.

 43
Author: CharlesB, 2014-03-27 09:50:35

Note que uma diferença entre git remote --prune e git fetch --prune está a ser fixada, com commit 10a6cc8 , por Tom Miller (tmiller) (para o git 1.9/2.0, T1 2014):

Quando temos um ramo de rastreamento remoto chamado "frotz/nitfol "de um busca anterior, e o upstream agora tem um ramo chamado" * * frotz"**, fetch seria incapaz de remover "frotz/nitfol "com um" git fetch --prune"do rio acima.
o git informaria o usuário a usar "git remote prune" para corrigir o problema.
Então ... : quando um upstream repo tem uma ramificação ("frotz") com o mesmo nome como um ramo de hierarquia ("frotz/xxx", uma possível ramo de convenção de nomenclatura), git remote --prune foi sucesso (na limpeza remota de seguimento o ramo de seu repo), mas git fetch --prune estava falhando.

Já não.

Mude a forma como "fetch --prune " funciona movendo a operação de poda antes da operação de obtenção.
Desta forma, em vez de avisar o utilizador de conflito, ele corrige automaticamente.

 12
Author: VonC, 2017-05-23 12:34:44
No caso de alguém estar interessado. Aqui está um script de shell rápido que irá remover todos os ramos locais que não são rastreados remotamente. Uma palavra de cautela: isso vai se livrar de qualquer branch que não é rastreado remotamente, independentemente de ter sido fundido ou não. Se virem algum problema com isto, avisem-me e eu arranjo-o. etc.)

Guarde-o num ficheiro chamado git-rm-ntb (chame-lhe o que quiser) em PATH e execute:

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 $@
 8
Author: D.Mill, 2014-03-28 00:21:49