Liste et suppression commits Git qui sont sous aucune branche (ballants?)
-
04-10-2019 - |
Question
J'ai un dépôt Git avec beaucoup de commits qui sont sous aucune branche, je peux les git show
, mais lorsque je tente de branches de la liste qui les contiennent, il rapporte rien en retour.
Je pensais que c'est le commits / question des arbres ballants (à la suite de la branche -D), donc j'élagué la pension, mais je vois toujours le même comportement après:
$ git fetch origin
$ git fsck --unreachable
$ git fsck
Sortie Non, rien ballants (droit?). Mais le commettras existe
$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
et il n'est pas accessible par une branche en tant que
$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
donne pas de sortie.
Quel est exactement l'état de ce commis? Comment puis-je énumérer tous les commits dans un état semblable? Comment puis-je supprimer commits comme ceux?
La solution
Pas de sortie, rien ballants (à droite?)
Notez que commits appelés à partir de votre reflog sont considérés comme accessibles.
Quel est exactement l'état de ce commis? Comment puis-je énumérer tous les commits avec le même état
Passe --no-reflogs
pour convaincre git fsck
de vous les montrer.
Comment puis-je supprimer commits comme ceux?
Une fois vos entrées reflog sont expirés, ces objets seront alors aussi être nettoyés par git gc
.
d'expiration est régie par les gc.pruneexpire
, gc.reflogexpire
, et les paramètres de gc.reflogexpireunreachable
. Cf. git help config
.
Les valeurs par défaut sont tout à fait raisonnable.
Autres conseils
Pour supprimer tous les commits ballants et ceux accessibles depuis les reflogs faire ceci:
git reflog expire --expire-unreachable=now --all
git gc --prune=now
Mais soyez certain que ce soit ce que vous voulez. Je vous recommande de lire les pages de manuel, mais voici l'essentiel:
git gc
removes objets (inatteignables commits, arbres, blobs (fichiers)). Un objet est inaccessible si elle ne fait pas partie de l'histoire de quelque branche. En fait, il est un peu plus compliqué:
git gc
fait d'autres choses, mais ils ne sont pas pertinentes ici et non dangereux.
Les objets qui sont injoignables moins de deux semaines ne sont pas supprimés si nous utilisons --prune=now
qui signifie « supprimer des objets inaccessibles qui ont été créés avant maintenant ».
Les objets peuvent également être atteints par le reflog. Alors que les branches enregistrent l'histoire de certains projets, reflogs enregistrent l'histoire de ces branches. Si vous réformez, réinitialiser etc. commits sont retirés de l'histoire de la branche, mais git les maintient autour dans le cas où vous vous rendez compte que vous avez fait une erreur. Reflogs sont un moyen pratique pour savoir ce que destructeur (et d'autres) opérations ont été effectuées sur une branche (ou HEAD), ce qui rend plus facile d'annuler une opération destructrice.
Nous avons donc aussi d'enlever les reflogs pour enlever effectivement pas tout accessible à partir d'une branche. Nous le faisons en venant à échéance reflogs de --all
. Encore une fois git garde un peu des reflogs aux utilisateurs que nous avons protègent à nouveau pour lui dire de ne pas le faire. --expire-unreachable=now
Depuis que je l'utilise principalement reflog pour récupérer des opérations destructrices que j'utilise habituellement au lieu --expire=now
, qui zappe les reflogs complètement.
J'ai eu le même problème, après avoir suivi tous les conseils sur ce sujet:
git reflog expire --expire-unreachable=now --all
git gc --prune=now
git fsck --unreachable --no-reflogs # no output
git branch -a --contains <commit> # no output
git show <commit> # still shows up
Si ce n'est pas un reflog et non une branche, ... il doit être une balise
git tag # showed several old tags created before the cleanup
Je retire les balises avec git tag -d <tagname>
et refit le nettoyage, et les anciens commits étaient partis.
git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
probablement juste besoin d'être
git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042
faire rapport aussi sur les branches de Distants
J'ai eu un problème similaire. Je courus git branch --contains <commit>
, et il n'y a pas de sortie comme dans la question.
Mais même après l'exécution
git reflog expire --expire-unreachable=now --all
git gc --prune=now
mon commettras était encore accessible à l'aide git show <commit>
. En effet, l'un des commits dans son détaché / miroiter « branche » a été taguée. J'ai enlevé l'étiquette, a couru les commandes ci-dessus à nouveau, et je suis d'or. git show <commit>
retourné fatal: bad object <commit>
- exactement ce que je avais besoin. Espérons que cela aide quelqu'un d'autre qui était aussi coincé que moi.
par défaut git gc --prune=<date>
à pruneau objets plus qu'il ya deux semaines. Vous pouvez définir une date plus récente. Mais, les commandes git qui créent des objets en vrac seront généralement exécuter git gc --auto (qui perdent pruneaux objets si leur nombre est supérieur à la valeur de gc.auto variable de configuration).
Êtes-vous sûr de vouloir supprimer ces commits? Le réglage par défaut de gc.auto veillera à ce que les objets en vrac ne prennent pas une quantité excessive de la mémoire et le stockage d'objets en vrac pendant un certain laps de temps est généralement une bonne idée. De cette façon, si vous vous rendez compte demain que votre branche Deleted contenait vous engagerez-vous besoin, vous pouvez le récupérer.
Je frappé accidentellement la même situation et trouvé mes stashes contiennent référence à l'engagement inatteignable, et donc le commit injoignable présumé est accessible à partir stashes.
Ce sont ce que je l'ai fait pour le rendre vraiment inaccessible.
git stash clear
git reflog expire --expire-unreachable=now --all
git fsck --unreachable
git gc --prune=now