Parcourir les commits orphelins dans Git

102

Mon dépôt git est en quelque sorte devenu bancal - j'ai chargé msysgit ce matin et au lieu que le nom de la branche soit affiché après le répertoire actuel, il dit "((ref: re ...))", 'git status' signale tout comme un nouveau fichier, 'git log' et 'git reflog' me disent "fatal: mauvaise révision par défaut" HEAD "", et ainsi de suite.

Faire 'git reflog --all' ou 'gitk --all' me montre que le reste du dépôt est intact, mais il semble que la branche sur laquelle je travaillais vient de disparaître, ce qui explique pourquoi HEAD ne semble pas exister / pointer vers quoi que ce soit.

Je sais que git conserve toutes sortes de globes d'informations, et je suppose que mes commits viennent d'être orphelins, alors y a-t-il une commande qui me montrera ces commits afin que je puisse réinitialiser HEAD?

EDIT: Oh mon Dieu. J'ai découvert 'git fsck', et 'git fsck --full' signale "fatal: object 03ca4 ... is corrupted". Que diable puis-je faire à ce sujet?

EDIT: Oh cher oh cher. J'ai vérifié une autre branche, puis j'ai essayé de recréer la branche d'origine avec le même nom en utilisant 'git checkout -b lostbranchname', et git dit "erreur: impossible de résoudre les références / heads / lostbranchname: aucune erreur, fatal: échec pour verrouiller ref pour la mise à jour: Aucune erreur ". «Aucune erreur» doit être une erreur particulièrement désagréable. Il semble donc qu'il traîne toujours, mais qu'il ne peut pas être utilisé et qu'il ne peut pas être tué.

EDIT: Super duper oh cher. J'ai fait un tas de déballage, de reconditionnement et de remplacement de choses comme suggéré ici: Comment récupérer des objets Git endommagés par une panne de disque dur? , mais maintenant je reçois un autre hachage signalé comme corrompu, pour quelque chose d'aussi inoffensif que «git status». Je pense que tout est arrosé. Git est adorable et tout, mais je ne devrais pas avoir à faire face à ce genre de chose.

Ben Hymers
la source
Concernant git checkout -b lostbranchname- si vous ne vous souciez que du nom de la branche (pas du contenu de celle-ci), vous pouvez supprimer (ou renommer) manuellement .git/refs/heads/lostbranchname- cela fera, espérons-le, l'affaire.
Antony Hatchkins
1
Et vous n'avez pas en amont où vous poussez ce dossier git?
Lakshman Prasad
1
Malheureusement non, c'est en fait une sorte de référentiel de substitution pour un système de contrôle de source inférieur, je l'utilise simplement localement pour obtenir toutes les fonctionnalités et les subtilités de git sans les tracas de l'autre système. Mais au moins l'autre système ne se corromp pas au hasard. Pourtant, cela signifie que tout ce que j'ai perdu, ce sont mes modifications depuis ma dernière connexion à l'autre système, que j'ai déjà récupéré. Il est temps de démarrer un nouveau référentiel!
Ben Hymers
7
J'hésiterais à dire que git vous a fait "gérer ce genre de chose" ou qu'il s'est corrompu. Rien d'autre qu'une sauvegarde ne peut être totalement stable contre la perte de données.
Cascabel
1
Je sais vraiment, je suis juste (naturellement) un peu vexé d'avoir perdu ma jolie histoire. Ce n'est pas la faute de git, n'importe quel autre système aurait les mêmes erreurs de système de fichiers.
Ben Hymers

Réponses:

135

Plutôt que de laisser cela ouvert, je pense que je vais donner une réponse à ma propre question. L'utilisation git reflog --allest un bon moyen de parcourir les commits orphelins - et en utilisant les hachages SHA1 à partir de là, vous pouvez reconstruire l'historique.

Dans mon cas cependant, le référentiel était corrompu donc cela n'a pas aidé; git fsckpeut vous aider à trouver et parfois à corriger les erreurs dans le référentiel lui-même.

Ben Hymers
la source
3
Merci. C'est le seul endroit où j'ai trouvé ces informations en essayant d'extraire une pull request orpheline sur github. J'ai résolu mon problème.
SystemParadox
6
au cas où quelqu'un voudrait tout dans gitk: [alias] orphank = !gitk --all --date-order ``git reflog | cut -c1-7``&(modifier: imaginez ces doubles backticks où les simples - échapper ne semble pas fonctionner ici)
mbx
1
Astuce géniale @mbx! Très utile pour pouvoir visualiser graphiquement les liens entre les commits orphelins!
Ben Hymers
@BenHymers Ce serait cool, si nous pouvions aussi avoir des lignes pointillées pour les relations de commit "rebase / squash". Je n'ai pas encore trouvé le moyen de le faire.
mbx
Je ne connaissais pas reflog lorsque j'ai écrit la réponse ci-dessus. C'est un outil tellement utile!
Jamey Hicks
17

Avec git 2.9.x / 2.10 (Q3 2016), vous n'aurez plus à utiliser git reflog --all, git reflogcela suffira.

Voir commit 71abeb7 (03 juin 2016) par SZEDER Gábor ( szeder) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 7949837 , 06 juil 2016)

reflog: continuez à parcourir les reflogcommits root passés

Si un référentiel contient plus d'un commit racine, alors son reflog HEAD peut contenir plusieurs "événements de création", c'est-à-dire des entrées dont la valeur "from" est la null sha1.
Le listage d'un tel reflog s'arrête prématurément à la première de ces entrées, même si le reflog contient encore des entrées plus anciennes.
Cela peut effrayer les utilisateurs en leur faisant croire que leur reflog a été tronqué après ' git checkout --orphan'.

Continuez à parcourir le reflog au-delà de ces événements de création en fonction de la valeur «nouvelle» de l'entrée reflog précédente.

VonC
la source
4

Une bonne caractéristique de git est qu'il détecte la corruption. Cependant, il n'inclut pas de correction d'erreur pour se protéger de la corruption.

J'espère que vous avez poussé le contenu de ce référentiel sur une autre machine ou que vous avez des sauvegardes pour récupérer les parties corrompues.

Je n'ai aucune expérience avec git sous windows mais je n'ai jamais vu ce genre de comportement avec git sous Linux ou OS X.

Jamey Hicks
la source
3

Je trouve généralement la git reflogsortie déroutante. Il est beaucoup plus facile pour moi de comprendre un graphe de commit à partir de git log --graph --reflog. Le remplacement du format pour afficher uniquement les résumés de validation peut également faciliter le suivi du graphique:

$ git alias graph "log --graph --all --format='%h %s%n        (%an, %ar)%d' --abbrev-commit
$ git graph --reflog

* f06abeb Add feature
|         (Sue Dakota, 4 days ago) (HEAD -> master)
* f126291 Fix the build
|         (Oski M. Wizard, 5 days ago) (origin/master, master)
* 3c4fb9c Break the build
|         (Alyssa P. Hacker, 5 days ago)
| * e3124bf fixup! More work for feature
| |         (Sue Dakota, 4 days ago)
| | * 6a7a52e Lost commit
| |/          (Sue Dakota, 4 days ago)
| * 69d9438 More work for feature
| |         (Sue Dakota, 2 weeks ago)
| * 8f69aba Initial work for feature
|/          (Sue Dakota, 3 weeks ago)
* d824fa9 Fix warnings from the linter
|         (Theo Ristudent, 4 weeks ago)
* 9f782b8 Fix tests flakes
|         (Tess Driven, 5 weeks ago)

De là, il est clair que e3124bfet 6a7a52esont des orphelins non référencés, et il y a le contexte de leurs commits ancêtres.

Jamesdlin
la source
M'a sauvé des heures de travail perdu tout à l'heure! supprimé accidentellement une branche locale qui avait des commits non poussés dessus, git reflog --allne les montre pas, avec git log --graph --reflogils étaient très visibles ...
Adam.Er8