Question Rétablir un fichier unique à une version précédente dans git [duplicate]


Cette question a déjà une réponse ici:

Existe-t-il un moyen de passer par différents commits sur un fichier. Dire que j'ai modifié un fichier 5 fois et je veux revenir à changer 2, après que j'ai déjà commis et poussé à un dépôt.

A ma connaissance, le seul moyen est de garder plusieurs branches, est-ce que j'ai bien compris? Si j'ai raison, je vais avoir des centaines de succursales dans quelques jours, donc je ne comprends probablement pas vraiment.

Quelqu'un pourrait-il clarifier cela s'il vous plaît?


451
2018-04-28 23:44


origine


Réponses:


Commençons par une description qualitative de ce que nous voulons faire (une grande partie de ceci est dite dans la réponse de Ben Straub). Nous avons effectué un certain nombre de validations, dont cinq ont changé un fichier donné, et nous souhaitons rétablir le fichier dans l'une des versions précédentes. Tout d'abord, git ne conserve pas les numéros de version pour les fichiers individuels. Il ne fait que suivre le contenu - un commit est essentiellement un instantané de l'arbre de travail, avec quelques métadonnées (par exemple, un message de validation). Donc, nous devons savoir quel commit a la version du fichier que nous voulons. Une fois que nous le saurons, nous devrons effectuer une nouvelle validation en rétablissant le fichier dans cet état. (Nous ne pouvons pas simplement traîner avec l'histoire, parce que nous avons déjà poussé ce contenu, et modifier les dégâts de l'histoire avec tout le monde.)

Commençons donc par trouver le bon engagement. Vous pouvez voir les commits qui ont apporté des modifications à des fichiers donnés très facilement:

git log path/to/file

Si vos messages de validation ne sont pas suffisants et que vous avez besoin de voir ce qui a été fait pour le fichier dans chaque commit, utilisez le -p/--patch option:

git log -p path/to/file

Ou, si vous préférez la vue graphique de gitk

gitk path/to/file

Vous pouvez également le faire une fois que vous avez démarré gitk via le menu de visualisation; Une des options pour une vue est une liste de chemins à inclure.

De toute façon, vous serez capable de trouver le SHA1 (hash) du commit avec la version du fichier que vous voulez. Maintenant, tout ce que vous avez à faire est ceci:

# 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'arborescence, il n'est donc pas nécessaire d'utiliser git add pour l'ajouter à l'index en préparation de l'engagement.)

Si votre fichier n'a pas d'historique simple (par exemple, renommage et copie), consultez l'excellent commentaire de VonC. git peut être dirigé à rechercher plus attentivement de telles choses, au détriment de la vitesse. Si vous êtes sûr que l'histoire est simple, vous n'avez pas besoin de vous embêter.


664
2018-04-29 00:26



Git est très flexible. Vous ne devriez pas avoir besoin de centaines de branches pour faire ce que vous demandez. Si vous voulez revenir à l'état précédent (et c'est effectivement un changement qui a déjà été commis et poussé), utilisez git revert. Quelque chose comme:

git revert a4r9593432 

où a4r9593432 représente les caractères de début du hachage du commit que vous voulez annuler.

Si la validation contient des modifications à de nombreux fichiers, mais que vous souhaitez simplement rétablir l'un des fichiers, vous pouvez utiliser git reset (le 2ème ou 3ème formulaire):

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 git reset est dangereux. Utilisation git checkout <hash> <file path> à la place, comme le suggère Jefromi.

Si vous voulez juste voir à quoi ressemblait le fichier dans le commit x, vous pouvez utiliser git show:

git show a4r9593432:path/to/file.txt

Pour toutes les commandes, il existe de nombreuses façons de faire référence à un commit autre que via le hash de commit (voir Nommer Commits dans le manuel d'utilisation de Git).


62
2018-04-29 00:29



Dites que vos 5 commits sont UNE, B, C, , E-UNE être le premier et E le dernier. Vous voulez revenir fichier.txt à la façon dont il était après commettre UNE. Vous n'avez pas besoin d'apprendre ou de mémoriser les différentes versions ou options des commandes git-reset et git-checkout. Courir:

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 sur tout objet dans un référentiel Git. Lorsqu'une référence de validation est donnée UNE (ou master ^ ou HEAD ~ 5 ou ...), suivi d'un deux-points, suivi d'un nom de fichier, il montrera le contenu de ce fichier tel qu'il était après cette validation. Ensuite, il suffit de rediriger la sortie dans le fichier.


12
2017-11-06 17:23



Vous pouvez prendre un diff qui annule les modifications souhaitées et les commet.

Par exemple. Si vous souhaitez annuler les modifications de la plage from..to, procédez comme suit

git diff to..from > foo.diff  # get a reverse diff
patch < foo.diff
git commit -a -m "Undid changes from..to".

5
2018-04-29 00:16



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 

Cela a très bien fonctionné pour moi.


5
2017-10-22 21:10



Git ne pense pas en termes de versions de fichiers. Une version de git est un instantané de l'arborescence entière.

Compte tenu de cela, ce que vous voulez vraiment, c'est un arbre qui a le dernier contenu de la plupart des fichiers, mais avec le contenu d'un fichier identique à ce qu'il était il y a 5 ans. Cela prendra la forme d'un nouveau commit en plus des anciens, et la dernière version de l'arbre aura ce que vous voulez.

Je ne sais pas s'il y a un one-liner qui retournera un seul fichier au contenu de 5 commits il y a, mais la solution lo-fi devrait fonctionner: checkout master~5, copiez le fichier ailleurs, passez la commande master, recopiez le fichier, puis validez.


4
2018-04-29 00:08