2010-05-21 8 views
22

J'ai un arbre git commeComment supprimer VRAIMENT une branche git (c'est-à-dire supprimer tous ses objets/commits)?

    A---B---C topic 
       /
      D---E---F---G master  <-- 

Je voudrais supprimer le sujet et tous les objets qu'il contient.

Je note l'ID SHA de sujet, puis tapez:

git branch -D topic 
git gc         # <-- I also tried prune here... 
git checkout -b temp <SHA1 ID of topic> 

Après la dernière commande, je vous attendre à obtenir une erreur (quelque chose comme « ID d'objet inexistant ... » ou somth comme ça.). Cependant, il n'y a pas d'erreur et gitk montre la même structure d'arbre que ci-dessus? Qu'est-ce qui me manque? - Je pensais que gc/prune est supposé supprimer tous les objets inaccessibles?

+2

La réponse de VonC explique les faits. Si vous voulez connaître la raison "philosophique", c'est simplement que git essaie très fort de ne pas vous laisser accidentellement supprimer quoi que ce soit. 'git gc' par lui-même est destiné à être une opération de nettoyage/réemballage. Vous devez dire quelque chose d'un peu plus fort pour l'effacer potentiellement du travail récent. – Cascabel

Répondre

4

Remarque Mai 2010: En tant que mentioned by Jakub, si votre branche a été fusionnée, le sujet sera toujours accessible.

Supposons ici qu'il n'y ait pas eu de fusion.
Puis, comme mentioned in the ProGit book et détaillée dans ce SO question:

git gc --prune=now 

devrait être assez (vous devez appeler directement git prune). Vous pouvez contrôler cela avec un git count-objects -v.
Modifier avril 2012: maxschlepzig dans les commentaires confirme que des étapes supplémentaires peuvent être nécessaires, comme indiqué dans Dukeanswer (mais sans le git repack).
Ainsi, au lieu d'un git gc --prune now:

git reflog expire --expire=now --all 
git gc --aggressive --prune=now 
+1

"Inaccessible" est en réalité encore plus fort que ce que vous sous-entendez ici. En ce qui concerne 'git-gc', un objet est accessible s'il est accessible depuis un reflog - et les reflogs mettent longtemps à expirer. Par exemple, vous auriez pu fusionner la branche en master, vous vous êtes rendu compte que c'était mauvais et remettre le master à la position précédente, et le commit serait considéré joignable jusqu'à l'expiration de l'entrée reflog (90 jours par défaut). – Cascabel

+3

Aussi, cela va sans dire, mais soyez très prudent en utilisant '--prune = now'. Ce serait horrible de se rendre compte que juste après être entré, un autre commit important a été effacé. – Cascabel

+0

merci les gars, vous rock! :) – Alan

24

Juste le pruneau gc est souvent ne suffit pas de se débarrasser des objets supplémentaires dans la prise en pension. Si les commits sont toujours référencés dans le refog, il ne considérera pas ces objets inaccessibles et donc mûrs pour l'élagage.

est ici ce qui a fonctionné pour moi:

git reflog expire --expire=now --all 
git gc --aggressive --prune=now 
git repack -a -d -l 

Cela fera quelques changements à l'histoire de votre pension, et peut bien les difficultés actuelles si les autres sont en fonction des branches vous séduiront.

Vous devrez peut-être reclasser votre référentiel pour voir une différence dans sa taille.

+0

Commentaires intéressants. +1 – VonC

+1

Je devais utiliser 'git reflog expire --expire = now --all'. Notez le "expire" ajouté. –

+0

Testé - et l'étape de remballage n'était pas nécessaire. – maxschlepzig