Ma situation est la suivante ... quelqu'un qui travaille sur le même référentiel a supprimé une branche de son référentiel local et distant ...
La plupart des gens qui ont posé des questions sur ce type de problème sur Stack Overflow ou sur d'autres sites ont le problème des branches qui apparaissent toujours dans leur liste de branches de suivi à distance git branch -a
en bas:
* master
develop
feature_blah
remotes/Origin/master
remotes/Origin/develop
remotes/Origin/feature_blah
remotes/Origin/random_branch_I_want_deleted
Cependant, dans MA situation, la branche qui ne devrait pas être là est locale:
* master
develop
feature_blah
random_branch_I_want_deleted
remotes/Origin/master
remotes/Origin/develop
remotes/Origin/feature_blah
Lorsque je fais l'une des choses suivantes, il n'est pas supprimé localement:
$ git Prune
J'ai aussi essayé:
$ git remote Prune Origin
$ git fetch --Prune
Plus d'infos utiles: Quand je vérifie git remote show Origin
c'est à quoi ça ressemble:
* 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)
Notez que ce n'est que dans la section intitulée Local branches configured for 'git pull':
Pourquoi?
Je ne vous en veux pas d'être frustré à ce sujet. La meilleure façon de regarder est la suivante. Il existe potentiellement trois versions de chaque branche distante:
refs/heads/master
)refs/remotes/...
)refs/remotes/Origin/master
)refs/heads/master
)Commençons par git Prune
. Cela supprime les objets qui ne sont plus référencés, cela ne supprime pas les références. Dans votre cas, vous avez une branche locale. Cela signifie qu'il existe une référence nommée random_branch_I_want_deleted
qui fait référence à certains objets représentant l'historique de cette branche. Donc, par définition, git Prune
ne supprimera pas random_branch_I_want_deleted
. Vraiment, git Prune
est un moyen de supprimer les données qui se sont accumulées dans Git mais qui ne sont référencées par rien. En général, cela n’affecte pas votre vue des branches.
git remote Prune Origin
et git fetch --Prune
fonctionnent tous deux sur des références sous refs/remotes/...
(nous les désignerons par références à distance). Cela n'affecte pas les branches locales. La version git remote
est utile si vous souhaitez uniquement supprimer des références distantes sous une télécommande particulière. Sinon, les deux font exactement la même chose. En bref, git remote Prune
et git fetch --Prune
agissent sur le numéro 2 ci-dessus. Par exemple, si vous supprimez une branche à l'aide de l'interface graphique Web de git et ne souhaitez plus qu'elle apparaisse dans votre liste de branches locales (git branch -r
), il s'agit de la commande à utiliser.
Pour supprimer une branche locale, vous devez utiliser git branch -d
(ou -D
s'il n'est fusionné nulle part). FWIW, il n’existe pas de commande git pour supprimer automatiquement les branches de suivi locales si une branche distante disparaît.
git remote Prune
et git fetch --Prune
font la même chose: supprimer les références des branches qui n'existent pas dans la télécommande, comme vous l'avez dit. La deuxième commande se connecte à la télécommande et récupère ses branches actuelles avant l'élagage.
Cependant, il ne touche pas les branches locales que vous avez extraites, vous pouvez simplement les supprimer avec
git branch -d random_branch_I_want_deleted
Remplacez -d
par -D
si la branche n'est pas fusionnée ailleurs
git Prune
fait quelque chose de différent, il purge les objets inaccessibles, ces commits qui ne sont accessibles dans aucune branche ni étiquette, et ne sont donc plus nécessaires.
Notez que la différence entre git remote --Prune
et git fetch --Prune
est corrigée, avec commit 10a6cc8 , par Tom Miller (tmiller
) (pour git 1.9/2.0, Q1 2014):
Lorsque nous avons une branche de suivi à distance nommée "
frotz/nitfol
" à partir d'une extraction précédente et que l'amont a maintenant une branche nommée "** frotz "**,fetch
ne parviendrait pas à supprimer"frotz/nitfol
"avec un"git fetch --Prune
"de l'amont.
git demanderait à l'utilisateur d'utiliser "git remote Prune
" pour résoudre le problème.
Donc: quand un dépôt en amont a une branche ("frotz") avec le même nom qu'un hiérarchie de branche ("frotz/xxx", un possible convention de dénomination de branche ), git remote --Prune
réussissait (en nettoyant la télécommande suivi de branche depuis votre référentiel), mais git fetch --Prune
échouait.
Plus maintenant:
Changez la façon dont "
fetch --Prune
" fonctionne en déplaçant l'opération d'élagage avant l'opération d'extraction.
Ainsi, au lieu d’avertir l’utilisateur d’un conflit, il le corrige automatiquement.
Dans le cas où quelqu'un serait intéressé. Voici un script Shell rapide qui supprimera toutes les branches locales qui ne sont pas suivies à distance. Un mot d'avertissement: cela supprimera toute branche qui n'est pas dépistée à distance, qu'elle ait été fusionnée ou non.
Si vous voyez un problème avec ceci, faites-le-moi savoir et je le corrigerai (etc. etc.)
Enregistrez-le dans un fichier nommé git-rm-ntb
(appelez-le comme bon vous semble) sur PATH
et exécutez-le:
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 $@