J'essaye de récupérer mon travail. Je l'ai fait bêtement git reset --hard
, mais avant cela, je ne faisais que et je ne get add .
faisais pas git commit
. Veuillez aider! Voici mon journal:
MacBookPro:api user$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# modified: .gitignore
...
MacBookPro:api user$ git reset --hard
HEAD is now at ff546fa added new strucuture for api
Est-il possible d'annuler git reset --hard
dans cette situation?
Réponses:
Vous devriez pouvoir récupérer tous les fichiers que vous avez ajoutés à l'index (par exemple, comme dans votre situation, avec
git add .
) bien que cela puisse être un peu de travail. Afin d'ajouter un fichier à l'index, git l'ajoute à la base de données d'objets, ce qui signifie qu'il peut être récupéré tant que le garbage collection n'a pas encore eu lieu. Il y a un exemple de la façon de faire cela donné dans la réponse de Jakub Narębski ici:Cependant, j'ai essayé cela sur un référentiel de test, et il y a eu quelques problèmes -
--cached
devrait être--cache
, et j'ai trouvé que cela ne créait pas réellement le.git/lost-found
répertoire. Cependant, les étapes suivantes ont fonctionné pour moi:Cela devrait afficher tous les objets de la base de données d'objets qui ne sont accessibles par aucune référence, dans l'index ou via le reflog. La sortie ressemblera à ceci:
... et pour chacun de ces blobs, vous pouvez faire:
Pour sortir le contenu du fichier.
Trop de sortie?
Mise à jour en réponse au commentaire de sehe ci-dessous:
Si vous constatez que de nombreuses validations et arborescences sont répertoriées dans la sortie de cette commande, vous souhaiterez peut-être supprimer de la sortie tous les objets référencés à partir de validations non référencées. (En règle générale, vous pouvez revenir à ces commits via le reflog de toute façon - nous sommes simplement intéressés par les objets qui ont été ajoutés à l'index mais qui ne peuvent jamais être trouvés via un commit.)
Tout d'abord, enregistrez la sortie de la commande, avec:
Maintenant, les noms d'objet de ces commits inaccessibles peuvent être trouvés avec:
Ainsi, vous pouvez trouver uniquement les arbres et objets qui ont été ajoutés à l'index, mais non validés à aucun moment, avec:
Cela réduit énormément le nombre d'objets que vous devrez considérer.
Mise à jour: Philip Oakley ci-dessous suggère une autre façon de réduire le nombre d'objets à prendre en compte, qui consiste à ne considérer que les fichiers les plus récemment modifiés sous
.git/objects
. Vous pouvez les trouver avec:(J'ai trouvé cette
find
invocation ici .) La fin de cette liste pourrait ressembler à:Dans ce cas, vous pouvez voir ces objets avec:
(Notez que vous devez supprimer le
/
à la fin du chemin pour obtenir le nom de l'objet.)la source
J'ai juste fait un
git reset --hard
et perdu un commit. Mais je connaissais le hachage de commit, donc j'ai pu le fairegit cherry-pick COMMIT_HASH
pour le restaurer.Je l'ai fait quelques minutes après avoir perdu le commit, cela peut donc fonctionner pour certains d'entre vous.
la source
git reflog
, par exemplegit reset --hard
->git reflog
(en regardant le hachage HEAD @ {1}) et enfingit cherry-pick COMMIT_HASH
git reset --hard
(en supposant que vous n'ayez rien fait d'autre après cette commande) estgit reset --hard @{1}
Grâce à Mark Longair, j'ai récupéré mes affaires!
J'ai d'abord enregistré tous les hachages dans un fichier:
Ensuite, je les mets tous (en supprimant le `` blob inaccessible '') dans une liste et je mets les données dans de nouveaux fichiers ... vous devez choisir vos fichiers et les renommer à nouveau dont vous avez besoin ... mais je n'en avais besoin que de quelques-uns fichiers..espérons que cela aide quelqu'un ...
la source
mkdir lost; git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") | grep -Po '\s\S{40}$' | xargs -i echo "git show {} > lost/{}.blob" | sh
. Les fichiers finiront danslost/*.blob
La solution de @ Ajedi32 dans les commentaires a fonctionné pour moi exactement dans cette situation.
Notez que toutes ces solutions reposent sur le fait qu'il n'y a pas de git gc, et certaines d'entre elles peuvent en causer un, donc je compresserais le contenu de votre répertoire .git avant d'essayer quoi que ce soit afin que vous ayez un instantané auquel revenir si vous ne le faites pas ne travaille pas pour toi.
la source
git reset --hard
, qui a gâché mon dépôt d'une manière inconnue. @Duncan, que fait le @ {1}? et de quel commentaire parlez-vous? Est-ce la réinitialisation d'ungit reset
?Ran dans le même problème, mais n'avait pas ajouté les modifications à l'index. Donc, toutes les commandes ci-dessus ne m'ont pas apporté les modifications souhaitées.
Après toutes les réponses élaborées ci-dessus, c'est un indice naïf, mais cela sauvera peut-être quelqu'un qui n'y a pas pensé en premier, comme je l'ai fait.
En désespoir de cause, j'ai essayé d'appuyer sur CTRL-Z dans mon éditeur (LightTable), une fois dans chaque onglet ouvert - cela a heureusement récupéré le fichier dans cet onglet, à son dernier état avant le
git reset --hard
. HTH.la source
C'est probablement évident pour les professionnels git, mais je voulais le mettre en place car dans ma recherche effrénée, je n'ai pas vu cela évoqué.
J'ai mis en scène certains fichiers et fait un
git reset --hard
, un peu paniqué, puis j'ai remarqué que mon statut montrait tous mes fichiers toujours en cours ainsi que toutes leurs suppressions non mises en scène.À ce stade, vous pouvez valider ces modifications par étapes, tant que vous ne procédez pas à leurs suppressions. Après cela, il vous suffit de trouver le courage de faire
git reset --hard
une fois de plus, ce qui vous ramènera aux changements que vous aviez mis en scène et que vous venez de commettre.Encore une fois, ce n'est probablement rien de nouveau pour la plupart, mais j'espère que puisque cela m'a aidé et que je n'ai rien trouvé suggérant cela, cela pourrait aider quelqu'un d'autre.
la source
Dieu, je me suis tiré les cheveux jusqu'à ce que je tombe sur cette question et ses réponses. Je pense que la réponse correcte et succincte à la question posée n'est disponible que si vous rassemblez deux des commentaires ci-dessus, donc ici, tout est au même endroit:
Comme mentionné par chilicuil, exécutez
git reflog
pour identifier là-dedans le hachage de validation auquel vous souhaitez revenirComme mentionné par akimsko, vous ne voudrez probablement PAS faire un choix à moins d'avoir perdu un seul commit, vous devriez donc exécuter
git reset --hard <hash-commit-you-want>
Remarque pour les utilisateurs d'egit Eclipse: je n'ai pas trouvé de moyen de faire ces étapes dans Eclipse avec egit. Fermer Eclipse, exécuter les commandes ci-dessus à partir d'une fenêtre de terminal, puis rouvrir Eclipse a très bien fonctionné pour moi.
la source
Les solutions ci-dessus peuvent fonctionner, cependant, il existe des moyens plus simples de récupérer à partir de cela au lieu de passer par
git
une annulation complexe. Je suppose que la plupart des réinitialisations git se produisent sur un petit nombre de fichiers, et si vous utilisez déjà VIM, c'est peut-être la solution la plus rapide. La mise en garde est que vous devez déjà utiliserViM's
l'annulation persistante, que vous devriez utiliser de toute façon, car elle vous offre la possibilité d'annuler un nombre illimité de modifications.Voici les étapes:
Dans vim appuyez sur
:
et tapez la commandeset undodir
. Si vous avezpersistent undo
activé votre.vimrc
, il affichera un résultat similaire àundodir=~/.vim_runtime/temp_dirs/undodir
.Dans votre repo, utilisez
git log
pour connaître la dernière date / heure à laquelle vous avez effectué le dernier commitDans votre shell, accédez à votre
undodir
utilisationcd ~/.vim_runtime/temp_dirs/undodir
.Dans ce répertoire, utilisez cette commande pour trouver tous les fichiers que vous avez modifiés depuis le dernier commit
find . -newermt "2018-03-20 11:24:44" \! -newermt "2018-03-23" \( -type f -regextype posix-extended -regex '.*' \) \-not -path "*/env/*" -not -path "*/.git/*"
Ici "2018-03-20 11:24:44" est la date et l'heure du dernier commit. Si la date à laquelle vous avez effectué le
git reset --hard
est "2018-03-22", utilisez "2018-03-22", puis "2018-03-23". Ceci est dû à une bizarrerie de find, où la limite inférieure est inclusive et la limite supérieure est exclusive. https://unix.stackexchange.com/a/70404/242983Ensuite, allez dans chacun des fichiers, ouvrez-les dans vim et faites un "20m plus tôt". Vous pouvez trouver plus de détails sur «plus tôt» en utilisant «h plus tôt». Ici
earlier 20m
signifie revenir à l'état du fichier 20 minutes en arrière, en supposant que vous avez fait legit hard --reset
, 20 minutes en arrière. Répétez cette opération sur tous les fichiers crachés par lafind
commande. Je suis sûr que quelqu'un peut écrire un script qui combinera ces choses.la source
J'utilise IntelliJ et j'ai simplement pu parcourir chaque fichier et faire:
Edit -> reload from disk
Heureusement, je venais juste de faire un
git status
juste avant d'effacer mes modifications de travail, donc je savais exactement ce que je devais recharger.la source
Se souvenir de votre hiérarchie de fichiers et utiliser la technique de Mark Longair avec la modification de Phil Oakley donne des résultats spectaculaires.
Essentiellement, si vous avez au moins ajouté les fichiers au référentiel mais ne l'avez pas validé, vous pouvez restaurer en utilisant de manière interactive
git show
, inspecter le journal et utiliser la redirection shell pour créer chaque fichier (en vous souvenant de votre chemin d'intérêt).HTH!
la source
Si vous avez récemment examiné un,
git diff
il existe un autre moyen de récupérer des incidents comme celui-ci, même si vous n'avez pas encore mis en scène les modifications: si la sortie degit diff
est toujours dans la mémoire tampon de votre console, vous pouvez simplement faire défiler vers le haut, copier-coller le diff dans un fichier et utiliser l'patch
outil pour appliquer la diff à votre arbre:patch -p0 < file
. Cette approche m'a sauvé plusieurs fois.la source