Retour d'un fichier unique à une version précédente dans git [dupliquer]
cette question a déjà une réponse ici:
- réinitialiser ou retourner un fichier spécifique à une révision spécifique en utilisant Git? 29 réponses
y a-t-il un moyen de passer par différentes propagations dans un fichier. Disons que j'ai modifié un fichier 5 fois et que je veux revenir en arrière pour changer 2, Après que j'ai déjà engagé et poussé dans un dépôt.
à mon avis, le seul moyen est de garder beaucoup de branches, est-ce que j'ai raison? Si j'ai raison, j'aurai des centaines de branches dans quelques jours, donc je ne comprends probablement pas vraiment.
est-ce que quelqu'un peut clarifier ça s'il vous plaît?
6 réponses
commençons par une description qualitative de ce que nous voulons faire (une grande partie de cela est dit dans la réponse de Ben Straub). Nous avons fait un certain nombre de commits, dont cinq changé d'un fichier donné, et nous voulons rétablir une des versions précédentes. Tout d'abord, git ne garde pas les numéros de version des fichiers individuels. Il ne fait que suivre le contenu - une propagation est essentiellement un instantané de l'arbre de travail, ainsi que certaines métadonnées (par exemple un message de propagation). Donc, nous devons savoir quel commit a le la version du fichier que nous voulons. Une fois que nous le saurons, nous aurons besoin de faire une nouvelle propagation en retournant le fichier dans cet état. (On ne peut pas se moquer de l'histoire, Parce qu'on a déjà poussé ce contenu, et éditer l'histoire déconne avec tout le monde.)
alors commençons par trouver le bon commit. Vous pouvez voir les propagations qui ont fait des modifications à des fichiers donnés très facilement:
git log path/to/file
si vos messages de propagation ne sont pas assez bons, et vous besoin de voir ce qui a été fait au fichier dans chaque propagation, utilisez l'option -p/--patch
:
git log -p path/to/file
Ou, si vous préférez la vue graphique de gitk
gitk path/to/file
vous pouvez également faire cela une fois que vous avez commencé gitk à travers le menu view; une des options pour une view est une liste de chemins à inclure.
dans tous les cas, vous pourrez trouver le SHA1 (hachage) de la propagation avec la version du fichier que vous voulez. Maintenant, tout ce que vous avez à faire est-ce:
# get the version of the file from the given commit
git checkout <commit> path/to/file
# and commit this modification
git commit
(la commande checkout lit d'abord le fichier dans l'index, puis le copie dans l'arbre de travail, il n'est donc pas nécessaire d'utiliser git add
pour l'ajouter à l'index en préparation à la propagation.)
si votre fichier peut ne pas avoir un historique simple (par exemple renom et copies), voir l'excellent commentaire de VonC. git
peut être dirigé pour rechercher plus soigneusement de telles choses, au détriment de la vitesse. Si vous êtes confiant sur l'histoire de l' simple, vous n'avez pas besoin de s'embêter.
Git est très flexible. Vous ne devriez pas avoir des centaines de succursales à faire ce que vous demandez. Si vous voulez revenir à l'État depuis le 2ème changement( et c'est en effet un changement qui était déjà engagé et poussé), utilisez git revert
. Quelque chose comme:
git revert a4r9593432
où a4r9593432 est le caractère de départ du hachage de la propagation que vous voulez annuler.
si la propagation contient des modifications beaucoup de fichiers, mais vous voulez juste pour revenir simplement l'un des fichiers, vous pouvez utiliser git reset
(la 2e ou 3e):
git reset a4r9593432 -- path/to/file.txt
# the reverted state is added to the staging area, ready for commit
git diff --cached path/to/file.txt # view the changes
git commit
git checkout HEAD path/to/file.txt # make the working tree match HEAD
mais c'est assez complexe, et réinitialiser git est dangereux. Utilisez git checkout <hash> <file path>
à la place, comme le suggère Jefromi.
si vous voulez juste voir à quoi ressemblait le fichier dans commit x, vous pouvez utiliser git show
:
git show a4r9593432:path/to/file.txt
pour l'ensemble des les commandes, il y a plusieurs façons de faire référence à une propagation autre que par le biais du hachage de propagation (voir Naming Commits dans le manuel D'utilisation de Git).
Dire votre 5 validations sont Un , B , C , D , E -- Un les premiers et les E le plus tard. Vous voulez retourner le fichier .txt à la façon dont il a été après commit Un . Vous n'avez pas besoin d'apprendre ou de vous souvenir des différentes versions ou options des commandes git-reset et git-checkout. Exécuter:
git show A:file.txt >file.txt
# If you want to commit the older version:
git add file.txt
git commit
la commande git-show affiche le contenu ou les informations de n'importe quel objet dans un dépôt Git. Lorsqu'on lui donne une référence de commit comme A (ou master^ ou HEAD~5 or ...), suivie d'une virgule, suivie par un nom de fichier, il vous montrera le contenu de ce fichier tel qu'il était après que s'engager. Ensuite, c'est juste une question de rediriger la sortie dans le fichier.
vous pouvez prendre une diff qui annule les changements que vous voulez et commettre cela.
E. G. Si vous voulez annuler les changements dans la gamme from..to
, faites ce qui suit
git diff to..from > foo.diff # get a reverse diff
patch < foo.diff
git commit -a -m "Undid changes from..to".
extrait d'ici: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html
git revert <commit>
git reset
git add <path>
git commit ...
git reset --hard # making sure you didn't have uncommited changes earlier
ça a très bien marché pour moi.
Git ne pense pas en termes de versions de fichiers. Une version en git est un instantané de l'arbre entier.
étant donné cela, ce que vous voulez vraiment est un arbre qui a le dernier contenu de la plupart des fichiers, mais avec le contenu d'un fichier la même chose qu'il y a 5 commits. Cela prendra la forme d'un nouveau commit sur les anciens, et la dernière version de l'arbre aura ce que vous voulez.
Je ne sais pas s'il y a une doublure qui va revenir un seul fichier au contenu de 5 commits ago, mais la solution lo-fi devrait fonctionner: checkout master~5
, copier le fichier ailleurs , checkout master
, copier le fichier en arrière, puis commit.