Trouver et restaurer un fichier supprimé dans un dépôt Git
dis que je suis dans un dépôt Git. Je supprime un fichier et je commets ce changement. Je continue à travailler et à faire d'autres commits. Ensuite, je trouve que j'ai besoin de restaurer ce fichier.
je sais que je peux vérifier un fichier en utilisant git checkout HEAD^ foo.bar
, mais je ne sais pas vraiment quand ce fichier a été supprimé.
- quel serait le moyen le plus rapide de trouver la propagation qui supprime un nom de fichier donné?
- quelle serait la meilleure façon d'obtenir ce fichier de retour dans ma copie de travail?
j'espère que je n'aurai pas à parcourir manuellement mes journaux, à vérifier l'ensemble du projet pour un SHA donné, puis à copier manuellement ce fichier dans ma caisse de projet originale.
19 réponses
trouver la dernière propagation qui a affecté le chemin donné. Comme le fichier n'est pas dans la propagation principale, cette propagation a dû le supprimer.
git rev-list -n 1 HEAD -- <file_path>
puis vérifier la version à la propagation avant, en utilisant le symbole caret ( ^
):
git checkout <deleting_commit>^ -- <file_path>
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 vous avez L'option EXTENDED_GLOB activée, l'accent circonflexe ne fonctionne pas. Vous pouvez utiliser ~1
à la place.
git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
- utilisez
git log --diff-filter=D --summary
pour obtenir toutes les propagations qui ont supprimé des fichiers et les fichiers supprimés; - Utiliser
git checkout $commit~1 filename
pour restaurer le fichier supprimé.
où $commit
est la valeur de la propagation que vous avez trouvée à 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 en cherchant à 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 la suivante:
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 <some commit where you know the file existed>
maintenant il est temps d'exécuter le test automatisé. La commande shell '[ -e foo.bar ]'
renvoie 0 si foo.bar
existe, et 1 autrement. La commande " run "de git-bisect
utilisera la recherche binaire pour trouver automatiquement la première propagation lorsque le test échoue. Il commence à la moitié de la fourchette donnée (du bon au mauvais) et le coupe en deux sur la base du résultat de la test spécifié.
git bisect run '[ -e foo.bar ]'
Maintenant vous êtes à la commit qui l'a supprimé. De là, vous pouvez revenir à l'avenir et utiliser git-revert
pour annuler le changement,
git bisect reset
git revert <the offending commit>
ou vous pouvez revenir en arrière une commit et inspecter manuellement les dommages:
git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .
Ma nouvelle préférée alias, basé sur bonyiii 's réponse (upvoted), et de ma propre réponse sur " Passer un argument à un Git commande alias ":
git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- )~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- )~1 | grep '^D' | cut -f 2); }; f'
j'ai perdu un fichier supprimé par erreur quelques engage dans le passé?
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 -- "")^ -- ""
et jegan ajoute dans les commentaires :
pour définir l'alias à partir de 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, c'est un moyen facile avec les commandes de base:
liste Toutes les propagations 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 la seconde à la dernière commit.
git checkout {second to last commit} -- path/to/file
pour restaurer un fichier supprimé et Commité:
git reset HEAD some/path
git checkout -- some/path
il a été testé sur la version 1.7.5.4 de Git.
Si vous faites des modifications et supprimé un fichier, mais pas le commettre, et maintenant que vous avez rompu vos modifications
git checkout -- .
mais vos fichiers supprimés ne sont pas retournés, vous faites simplement la commande suivante:
git checkout <file_path>
et presto, votre dossier est de retour.
j'ai cette solution .
-
récupérez l'id de la propagation 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*
# recommandé si vous avez à peine se souvenir de n'importe quoi
-
-
vous devriez obtenir quelque chose comme:
commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 auteur: Alexander Orlov Date: Jeu Mai 12 23: 44: 27 2011 +0200
replaced deprecated GWT class - gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script
commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 auteur: Alexander Orlov Date: Jeu Mai 12 22: 10: 22 2011 +0200
3 . Maintenant, en utilisant la validation id bfe68bd117e1091c96d2976c99b3bcc8310bebe7 do:
git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java
comme l'id de propagation renvoie à la propagation où le fichier a déjà été supprimé, vous devez renvoyer à la propagation juste avant bfe68b ce que vous pouvez faire en ajoutant ^1
. Cela signifie: Donnez-moi le commit juste avant bfe68b.
dans de nombreux cas, il peut être utile d'utiliser coreutils (grep, sed, etc.) en conjonction avec Git. Je connais déjà assez bien ces outils, mais pas autant. 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 <rev>^ -- path/to/refound/deleted_file.c
tout comme d'autres l'ont dit avant moi.
Le fichier sera restauré à l'état qu'il avait avant de les enlever. N'oubliez pas de ré-engager pour l'arbre de travail si vous souhaitez le garder.
git undelete path/to/file.ext
-
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 -- )^ -- " -'
-
ensuite utiliser:
git undelete path/to/file.ext
cet alias vérifie d'abord pour trouver le dernier commit où ce fichier existait, puis fait une vérification git de ce chemin de fichier à partir de ce dernier commit où ce fichier existait. source
donc j'ai dû restaurer un tas de fichiers supprimés à partir d'une propagation spécifique et je l'ai géré avec deux commandes:
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ --
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD
(noter l'espace de fuite à la fin de chaque commande.)
les fichiers avaient été ajoutés à la .gitignore fichier et ensuite effacé avec git rm, j'avais besoin de restaurer les fichiers mais alors unstage. J'ai eu des centaines de fichiers à restaurer, 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
restaurer 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
j'avais la même question. Sans le savoir, j'avais créé un bancales commettre .
Liste balançant s'engage
git fsck --lost-found
Inspecter chaque balançant commettre
git reset --hard <commit id>
Mes fichiers sont réapparus quand je suis passé à la commit pendante.
git status
pour la raison:
“HEAD detached from <commit id where it detached>”
dans notre cas nous avons accidentellement supprimé des fichiers dans un commit et certains commit plus tard nous avons réalisé notre erreur et avons voulu récupérer tous les fichiers qui ont été supprimés mais pas ceux qui ont été modifiés.
basé sur L'excellente réponse de Charles Bailey voici mon un liner:
git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)
si vous connaissez la propagation qui a supprimé le(S) fichier (s), lancez cette commande où <SHA1_deletion>
est la propagation qui a supprimé le fichier:
git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --
la partie avant la pipe liste tous les fichiers qui ont été supprimés dans la propagation; ils sont tous des checkout de la propagation précédente pour les restaurer.