J'ai un référentiel Git avec beaucoup de commits qui ne sont sous aucune branche particulière, je peux git show
les faire, mais quand j'essaye de lister les branches qui les contiennent, il ne rapporte rien.
Je pensais que c'était le problème des commits / arborescence pendantes (à la suite de la branche -D), j'ai donc élagué le dépôt, mais je vois toujours le même comportement après cela:
$ git fetch origin
$ git fsck --unreachable
$ git fsck
Pas de sortie, rien de balançant (non?). Mais le commit existe
$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
et il n'est accessible via aucune succursale car
$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
ne donne aucune sortie.
Quel est exactement l'état de ce commit? Comment puis-je lister tous les commits dans un état similaire? Comment puis-je supprimer des commits comme ceux-ci?
git
branch
git-dangling
Samer Buna
la source
la source
Réponses:
Notez que les commits référencés dans votre reflog sont considérés comme atteignables.
Passez
--no-reflogs
à convaincregit fsck
de vous les montrer.Une fois vos entrées reflog expirées, ces objets seront également nettoyés par
git gc
.Expiration est régie par les
gc.pruneexpire
,gc.reflogexpire
et lesgc.reflogexpireunreachable
paramètres. Cf.git help config
.Les valeurs par défaut sont toutes assez raisonnables.
la source
git help glossary
définit de cette façon… alors que sa définition de «accessible» n'est pas restreinte de cette façon, ils sont donc contradictoires. Drôle - donc ce que j'ai dit est en fait cohérent avec la confusion dansgitglossary
… Ce ne sont pas les concepts qui prêtent à confusion, cependant, juste la terminologie. Le fait est que les commits «pendantes» sont ceux sur lesquels rien d' autre ne pointe. Est-ce que cela aiderait si je dis "reflogs pour des commits autrement inaccessibles"…?master
vous êtes sur une branche , vous le faitesgit commit
et obtenez un commit000001
. Ensuite, vous faitesgit commit --amend
, ce qui vous donne un engagement000002
. Il n'y a plus de balises ou de branches pointant vers000001
, et vous ne pouvez pas le voir dans votre journal sans l'--reflog
option, mais si vous le souhaitez, vous pouvez toujours y accéder avecgit checkout 000001
. Maintenant, la question est: est-ce000001
qu'un commit suspendu , ou un commit inaccessible , ou ni l'un ni l'autre, ou les deux?Pour supprimer tous les commits en suspens et ceux accessibles à partir des reflogs, procédez comme suit:
Mais assurez-vous que c'est ce que vous voulez. Je vous recommande de lire les pages de manuel mais voici l'essentiel:
git gc
supprime les objets inaccessibles (commits, arborescences, blobs (fichiers)). Un objet est inaccessible s'il ne fait pas partie de l'histoire d'une branche. En fait, c'est un peu plus compliqué:git gc
fait d'autres choses mais elles ne sont pas pertinentes ici et ne sont pas dangereuses.Les objets inaccessibles de moins de deux semaines ne sont pas supprimés, nous utilisons donc
--prune=now
ce qui signifie «supprimer les objets inaccessibles qui ont été créés auparavant».Les objets peuvent également être atteints via le reflog. Alors que les succursales enregistrent l'historique de certains projets, les reflogs enregistrent l'histoire de ces succursales. Si vous modifiez, réinitialisez, etc., les validations sont supprimées de l'historique de la branche mais git les garde au cas où vous vous rendriez compte que vous avez fait une erreur. Les Reflogs sont un moyen pratique de savoir quelles opérations destructives (et autres) ont été effectuées sur une branche (ou HEAD), ce qui facilite l'annulation d'une opération destructive.
Nous devons donc également supprimer les reflogs pour supprimer tout ce qui n'est pas accessible depuis une branche. Nous le faisons en expirant les
--all
reflogs. Encore une fois git garde un peu des reflogs pour protéger les utilisateurs que nous avons à nouveau pour lui dire de ne pas le faire:--expire-unreachable=now
.Comme j'utilise principalement le reflog pour récupérer des opérations destructives, j'utilise généralement à la
--expire=now
place, ce qui zappe complètement les reflogs.la source
git reflog expire --expire-unreachable=now --all
laisse tomber toutes vos cachettes!J'ai eu le même problème, toujours après avoir suivi tous les conseils de ce fil:
Si ce n'est pas un reflog et pas une branche, ... ça doit être un tag !
J'ai supprimé les balises avec
git tag -d <tagname>
et refait le nettoyage, et les anciens commits avaient disparu.la source
a probablement juste besoin d'être
pour signaler également les succursales à partir de télécommandes
la source
git push -d origin next
n'aide pas.git fetch --prune
fait l'affaire. mais dans toutes les réponses, il me manque une vérification des balises qui font référence à ce commit. Je ne sais toujours pas comment vérifier les balises avec un commit (j'ai tout supprimé).git fsck --unreachable
communiquent donc réellement sur le réseau avec la télécommande afin de savoir quels commits sont accessibles?git fsck --unreachable
n'a pas besoin de communiquer sur le réseau avec la télécommande pour savoir quelles branches distantes contiennent quels commits. Les informations de la branche distante sont stockées localement, sous par exemple.git/refs/remotes/origin
(ou danspacked-refs
).J'ai eu un problème similaire. J'ai couru
git branch --contains <commit>
, et il n'a renvoyé aucune sortie comme dans la question.Mais même après avoir couru
mon commit était toujours accessible en utilisant
git show <commit>
. Cela était dû au fait que l'un des commits de sa "branche" détachée / suspendue était balisé. J'ai supprimé la balise, exécuté à nouveau les commandes ci-dessus et j'étais en or.git show <commit>
retournéfatal: bad object <commit>
- exactement ce dont j'avais besoin. Espérons que cela aide quelqu'un d'autre qui était aussi coincé que moi.la source
J'ai accidentellement rencontré la même situation et j'ai trouvé que mes cachettes contenaient une référence au commit inaccessible, et donc le commit présumé inaccessible était accessible à partir des cachettes.
C'est ce que j'ai fait pour le rendre vraiment inaccessible.
la source
git gc --prune=<date>
par défaut, élaguer les objets datant de plus de deux semaines. Vous pouvez définir une date plus récente. Mais, les commandes git qui créent des objets libres exécutent généralement git gc --auto (qui élague les objets libres si leur nombre dépasse la valeur de la variable de configuration gc.auto).Voulez-vous vraiment supprimer ces validations? Le paramètre par défaut de gc.auto garantira que les objets en vrac ne prennent pas une quantité déraisonnable de mémoire, et stocker les objets en vrac pendant un certain temps est généralement une bonne idée. De cette façon, si vous réalisez demain que votre branche supprimée contenait un commit dont vous aviez besoin, vous pouvez le récupérer.
la source