402 votes

Comment récupérer un commit perdu dans Git ?

Tout d'abord, j'ai obtenu "votre branche est en avance de 3 commits sur origin/master", puis mon application est revenue à un moment antérieur avec des changements antérieurs.

Comment puis-je récupérer ce que j'ai passé les 11 dernières heures à faire ?

0 votes

911voto

Amber Points 159296

git reflog est votre ami. Trouvez dans cette liste la commission sur laquelle vous voulez être et vous pouvez la réinitialiser (par exemple : git reset --hard e870e41 ).

(Si vous n'avez pas validé vos modifications... vous pourriez avoir des problèmes - validez tôt et validez souvent !)

0 votes

Le problème est survenu lorsque j'ai essayé de commiter... git reflog retourne " : HEAD@{0} : checkout : moving from following-users to ma....HEAD@{1} : commit : yo.... HEAD@{2} : commit : mis à jour une tonne....HEAD@{3} : checkout : passage de master à following-u...comment puis-je revenir à l'un de ces trois derniers ?

18 votes

Jetez un coup d'œil à git log HEAD@{1} . Si cela ressemble à la bonne série de commits, alors vous pouvez git reset HEAD@{1} .

7 votes

Seulement si les codes sont staged (en utilisant git add), ils sont conservés dans git et peuvent être retrouvés facilement en utilisant des commandes comme git fsck --lost-found .

173voto

jsexpert Points 704

Avant de répondre, ajoutons un peu de contexte, en expliquant ce qu'est cette HEAD est.

First of all what is HEAD?

HEAD est simplement une référence au commit actuel (le plus récent) sur la branche actuelle.
Il ne peut y avoir qu'un seul HEAD à un moment donné (à l'exclusion de git worktree ).

Le contenu de HEAD est stocké à l'intérieur .git/HEAD et il contient les 40 octets SHA-1 du commit actuel.


detached HEAD

Si vous n'êtes pas sur le dernier commit - ce qui signifie que HEAD pointe vers un commit antérieur dans l'historique, il est appelé detached HEAD .

Enter image description here

Sur la ligne de commande, cela ressemblera à ceci - SHA-1 à la place du nom de la branche, puisque la commande HEAD ne pointe pas vers l'extrémité de la branche actuelle :

Enter image description here

Enter image description here


Quelques options sur la façon de récupérer d'un HEAD détaché :


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Ceci va extraire une nouvelle branche pointant vers le commit désiré.
Cette commande effectuera un checkout vers un commit donné.
À ce stade, vous pouvez créer une branche et commencer à travailler à partir de ce point.

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Vous pouvez toujours utiliser le reflog également.
git reflog affichera tout changement qui a mis à jour le HEAD et en vérifiant l'entrée reflog souhaitée, on obtient la HEAD à cet engagement.

Chaque fois que le HEAD est modifié, il y aura une nouvelle entrée dans le fichier reflog

git reflog
git checkout HEAD@{...}

Cela vous ramènera à votre engagement souhaité

Enter image description here


_git reset --hard <commit_id>_

"Déplacez" votre TÊTE vers l'engagement souhaité.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Note : ( Depuis Git 2.7 ), vous pouvez également utiliser le git rebase --no-autostash également.

git revert <sha-1>

"Annuler" le commit ou la plage de commit donnée.
La commande reset va "annuler" tous les changements effectués dans le commit donné.
Un nouveau commit avec le patch d'annulation sera commis tandis que le commit original restera également dans l'historique.

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Ce schéma illustre quelle commande fait quoi.
Comme vous pouvez le voir ici, reset && checkout modifier le HEAD .

Enter image description here

50voto

Atri Points 4631

Une autre façon d'accéder au commit supprimé est d'utiliser la fonction git fsck commandement.

git fsck --lost-found

Cela donnera quelque chose comme la dernière ligne :

dangling commit xyz

Nous pouvons vérifier que c'est le même commit en utilisant reflog comme suggéré dans d'autres réponses. Maintenant nous pouvons faire un git merge

git merge xyz

Note :
Nous ne pouvons pas récupérer l'engagement avec fsck si nous avons déjà exécuté un git gc qui supprimera la référence à la livraison en suspens.

12voto

Ventrova Points 91

Essayez ceci, Cela montrera tous les commits enregistrés dans git pour une période de temps donnée.

git reflog

Trouvez l'engagement que vous voulez avec

git log HEAD@{3}

ou

git log -p HEAD@{3}    

Ensuite, vérifiez si c'est le bon :

git checkout HEAD@{3}

Cela créera une tête détachée pour ce commit. Ajoutez et livrez tout changement si nécessaire

git status 
git add
git commit -m "temp_work" 

Maintenant si vous voulez restaurer le commit vers une branche, disons master, vous devrez nommer cette branche switch to master puis merge to master.

git branch temp
git checkout master
git merge temp

Voici également un lien spécifique pour reflog sur un site de tutoriel Git : Tutoriel Git d'Atlassian

9voto

zean_7 Points 73

Cela m'est arrivé aujourd'hui même, et j'écris donc ce qui m'a sauvé la vie. Ma réponse est très similaire à celle de @Amber.

D'abord, j'ai fait un git reflog et a cherché le hash de ce commit particulier, puis a juste copié ce hash et a fait un git cherry-pick <hash> de cette branche. Cela a apporté tous les changements de ce commit perdu à ma branche actuelle, et a restauré ma foi en GIT.

Passez une bonne journée !

1 votes

Sauveteur, merci !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X