Rechercher et restaurer un fichier supprimé dans un référentiel Git

Disons que je suis dans un repository Git. Je supprime un fichier et commets ce changement. Je continue à travailler et à faire plus de commits. Ensuite, je trouve que je dois restaurer ce fichier.

Je sais que je peux extraire un fichier en utilisant git checkout HEAD^ foo.bar , mais je ne sais pas vraiment quand ce fichier a été supprimé.

  1. Quel serait le moyen le plus rapide de trouver le commit qui a supprimé un nom de fichier donné?
  2. Quel serait le moyen le plus simple de récupérer ce fichier dans ma copie de travail?

J’espère que je n’ai pas à parcourir manuellement mes journaux, à extraire l’intégralité du projet pour un SHA donné, puis à copier manuellement ce fichier dans ma vérification de projet d’origine.

Recherchez le dernier commit qui a affecté le chemin donné. Comme le fichier ne se trouve pas dans la validation HEAD, ce commit doit l’avoir supprimé.

 git rev-list -n 1 HEAD --  

Ensuite, vérifiez la version à la validation avant, en utilisant le symbole caret ( ^ ):

 git checkout ^ --  

Ou dans une commande, si $file est le fichier en question.

 git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file" 

Si vous utilisez zsh et que l’option EXTENDED_GLOB est activée, le symbole caret ne fonctionnera pas. Vous pouvez utiliser ~1 place.

 git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file" 
  1. Utilisez git log --diff-filter=D --summary pour obtenir tous les commits qui ont supprimé les fichiers et les fichiers supprimés;
  2. Utilisez git checkout $commit~1 filename pour restaurer le fichier supprimé.

$commit est la valeur du commit que vous avez trouvé à l’étape 1, par exemple e4cf499627

Pour restaurer tous les fichiers supprimés dans un dossier, entrez la commande suivante.

 git ls-files -d | xargs git checkout -- 

Je suis venu à cette question à la recherche de restaurer un fichier que je viens de supprimer, mais je n’avais pas encore commis le changement. Juste au cas où vous vous trouvez dans cette situation, tout ce que vous devez faire est le suivant:

git checkout HEAD -- path/to/file.ext

Si vous êtes fou, utilisez git-bisect . Voici ce qu’il faut faire:

 git bisect start git bisect bad git bisect good  

Maintenant, il est temps d’exécuter le test automatisé. La commande shell '[ -e foo.bar ]' renverra 0 si foo.bar existe et 1 sinon. La commande “run” de git-bisect utilisera la recherche binary pour trouver automatiquement le premier commit où le test échoue. Il commence à mi-chemin de la plage donnée (de bon à mauvais) et le réduit de moitié en fonction du résultat du test spécifié.

 git bisect run '[ -e foo.bar ]' 

Maintenant, vous êtes sur le commit qui l’a supprimé. A partir de là, vous pouvez revenir au futur et utiliser git-revert pour annuler le changement,

 git bisect reset git revert  

ou vous pouvez revenir en arrière un engagement et inspecter manuellement les dégâts:

 git checkout HEAD^ cp foo.bar /tmp git bisect reset cp /tmp/foo.bar . 

Mon nouvel alias préféré, basé sur la réponse de bonyiii (votée), et ma propre réponse sur ” Transmettez un argument à une commande d’alias Git “:

 git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f' 

J’ai perdu un fichier, supprimé par erreur il y a quelques commits?
Rapide:

 git restore my_deleted_file 

Crise évitée.


Robert Dailey propose dans les commentaires l’alias suivant:

 restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1" 

Et jegan ajoute dans les commentaires :

Pour définir l’alias depuis la ligne de commande, j’ai utilisé cette commande:

 git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 

Si vous connaissez le nom du fichier, c’est un moyen facile avec les commandes de base:

Liste tous les commits pour ce fichier.

 git log -- path/to/file 

Le dernier commit (le plus haut) est celui qui a supprimé le fichier. Donc, vous devez restaurer le deuxième à la dernière validation.

 git checkout {second to last commit} -- path/to/file 

Pour restaurer un fichier supprimé et validé:

 git reset HEAD some/path git checkout -- some/path 

Il a été testé sur Git version 1.7.5.4.

Si vous avez seulement apporté des modifications et supprimé un fichier, mais que vous ne l’avez pas validé, et que vous avez maintenant interrompu vos modifications

 git checkout -- . 

mais vos fichiers supprimés ne sont pas revenus, vous faites simplement la commande suivante:

 git checkout  

Et hop, votre dossier est de retour.

J’ai cette solution .

  1. Obtenez l’id de la validation où le fichier a été supprimé en utilisant l’une des méthodes ci-dessous.

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* git log --stat | grep --context=5 *word* # recommandé si vous vous souvenez à peine de quelque chose
  2. Vous devriez obtenir quelque chose comme:

commettre bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Auteur: Alexander Orlov Date: jeu 12 mai 2011 23:44:27 2011 +0200

 replaced deprecated GWT class - gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script 

commettre 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Auteur: Alexander Orlov Date: jeu mai 12 22:10:22 2011 +0200

3 . Maintenant, en utilisant l’ID de validation bfe68bd117e1091c96d2976c99b3bcc8310bebe7, faites:

 git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java 

Comme l’ID de validation référence le commit où le fichier a déjà été supprimé, vous devez référencer le commit juste avant bfe68b, ce que vous pouvez faire en ajoutant ^1 . Cela signifie: donnez-moi le commit juste avant bfe68b.

 git checkout /path/to/deleted.file 

Dans de nombreux cas, il peut être utile d’utiliser coreutils (grep, sed, etc.) en conjonction avec Git. Je connais déjà bien ces outils, mais Git moins. Si je voulais faire une recherche pour un fichier supprimé, je ferais ce qui suit:

 git log --raw | grep -B 30 $'D\t.*deleted_file.c' 

Quand je trouve la révision / commit:

 git checkout ^ -- path/to/refound/deleted_file.c 

Tout comme d’autres l’ont déjà dit.

Le fichier sera maintenant restauré à l’état qu’il avait avant la suppression. N’oubliez pas de le remettre sur l’arbre de travail si vous souhaitez le conserver.

git undelete path/to/file.ext

  1. Mettez ceci dans votre .bash_profile (ou tout autre fichier pertinent qui se charge lorsque vous ouvrez un shell de commande):

     git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -' 
  2. Ensuite, utilisez:

     git undelete path/to/file.ext 

Cet alias vérifie d’abord pour trouver le dernier commit où ce fichier existait, puis effectue une vérification git de ce chemin de fichier à partir du dernier commit où ce fichier existait. la source

J’ai donc dû restaurer un tas de fichiers supprimés à partir d’un commit spécifique et je l’ai géré avec deux commandes:

 git show  --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout ^ -- git show  --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(Notez l’espace à la fin de chaque commande.)

Les fichiers ont été ajoutés au fichier .gitignore puis effacés avec git rm, il me fallait restaurer les fichiers, puis les décompresser. J’avais des centaines de fichiers à restaurer, en tapant des choses manuellement pour chaque fichier, comme dans les autres exemples, allait être beaucoup trop lent.

 user@bsd:~/work/git$ rm slides.tex user@bsd:~/work/git$ git pull Already up-to-date. user@bsd:~/work/git$ ls slides.tex ls: slides.tex: No such file or directory 

Restaurez le fichier supprimé:

 user@bsd:~/work/git$ git checkout D .slides.tex.swp D slides.tex user@bsd:~/work/git$ git checkout slides.tex user@bsd:~/work/git$ ls slides.tex slides.tex 

Dans notre cas, nous avons accidentellement supprimé des fichiers dans un commit et certains plus tard, nous avons réalisé notre erreur et voulu récupérer tous les fichiers supprimés mais pas ceux qui ont été modifiés.

Sur la base de l’excellente réponse de Charles Bailey, voici mon seul article:

 git co $(git rev-list -n 1 HEAD -- )~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- )~1 head | grep '^D' | cut -f 2) 

Si vous connaissez le commit qui a supprimé le ou les fichiers, exécutez cette commande où est le commit qui a supprimé le fichier:

 git diff --diff-filter=D --name-only ~1  | xargs git checkout ~1 -- 

La partie avant le canal répertorie tous les fichiers qui ont été supprimés dans la validation; ils sont tous à la caisse de l’engagement précédent pour les restaurer.

J’ai eu la même question. Sans le savoir, j’avais créé un commit en suspens .

List dangling commits

git fsck --lost-found

Inspecter chaque engagement en suspens

git reset --hard

Mes fichiers ont réapparu lorsque je suis passé au commit en suspens.

git status pour la raison:

“HEAD detached from

 $ git log --diff-filter=D --summary | grep "delete" | sort