Réinitialisation matérielle d'un seul fichier

1006

J'ai actuellement trois fichiers modifiés dans mon répertoire de travail. Cependant, je veux que l'un d'eux soit réinitialisé à l'état HEAD.

Dans SVN, j'utiliserais svn revert <filename>(suivi svn update <filename>si nécessaire) mais dans Git je devrais utiliser git reset --hard. Cependant, cette commande ne peut pas fonctionner sur un seul fichier.

Existe-t-il un moyen dans Git d'annuler les modifications apportées à un seul fichier et de l'écraser avec une nouvelle copie HEAD?

Emiliano
la source
3
git checkoutci-dessous est la réponse. Dans git, "revert" est quelque chose que vous faites pour un commit. "Revert" rejoue l'inverse d'un commit historique dans votre répertoire de travail, vous pouvez donc faire un nouveau commit qui "annule" le commit annulé. Je trouve que c'est un point de confusion fréquent pour les gens venant de git depuis svn.
Dan Ray
Si vous êtes intéressé par la raison pour laquelle vous ne pouvez pas effectuer de réinitialisation matérielle avec les chemins, consultez ma réponse ici .
utilisateur
Cette question suppose que l'on sait ce qu'est une réinitialisation matérielle.

Réponses:

1811

Vous pouvez utiliser la commande suivante:

git checkout HEAD -- my-file.txt

... qui mettra à jour la copie de travail my-file.txtet son état dans l'index avec celui de HEAD.

--signifie essentiellement: traiter chaque argument après ce point comme un nom de fichier . Plus de détails dans cette réponse . Merci à VonC de l' avoir signalé.

Mark Longair
la source
58
Réponse plus complète. +1;) Pour le '-', voir aussi stackoverflow.com/questions/6561142/… (et, plus généralement, stackoverflow.com/questions/1192180/… )
VonC
8
N'oubliez pas non plus que vous pouvez référencer un commit précédent avec HEAD~1pour indiquer l'avant-dernier commit.
Ryanmt
14
Vous pouvez laisser de côté HEADsi vous êtes à la tête de la branche actuelle - voir norbauer.com/rails-consulting/notes/…
cxw
4
Avez-vous une idée de la raison pour laquelle la resetcommande (comme il est dit) "ne peut pas effectuer de réinitialisation matérielle avec les chemins d'accès", puis pourquoi la checkoutcommande n'est pas (ne peut pas être?) Utilisée pour réinitialiser en dur l'ensemble complet? (Je veux dire pourquoi il a été conçu ainsi.)
Sz.
1
@cxw Malheureusement, ce n'est pas tout à fait vrai. À partir de la page de manuel de git checkout: "Écraser les chemins dans l'arborescence de travail en les remplaçant par le contenu de l'index ou de <tree-ish>". C'est-à-dire si <tree-ish>est omis, quel que soit le contenu de l'index sera utilisé pour mettre à jour l'arborescence de travail. Cela peut ou non différer de HEAD.
tuntap
137

Réinitialiser à la tête:

Pour réinitialiser en dur un seul fichier sur HEAD:

git checkout @ -- myfile.ext

Notez que @c'est l'abréviation de HEAD. Une ancienne version de git peut ne pas prendre en charge la forme courte.

Réinitialiser l'index:

Pour réinitialiser en dur un fichier unique à l' index , en supposant que l'index n'est pas vide, sinon à HEAD:

git checkout -- myfile.ext

Le fait est que pour être sûr, vous ne voulez pas laisser de côté @ou à HEADpartir de la commande, sauf si vous voulez spécifiquement réinitialiser l'index uniquement.

Acumenus
la source
1
Que se passe-t-il avec le "-" avant monfichier.ext?
Lance Kind
3
@LanceKind Si je comprends bien, c'est utilisé pour délimiter une liste de noms de fichiers qui le suit. Sans cela, il y a des cas où git interprète les arguments de manière incorrecte.
Acumenus
2
Pas seulement les noms de fichiers. La convention largement utilisée sépare les options des arguments de position dans de nombreux utilitaires. Voir man bashpage. Également mentionné dans cette réponse: unix.stackexchange.com/a/187548/142855
boweeb
1
Classiquement, le --est utilisé pour indiquer le programme I've finished specifying "options", and from here on, everything will be a positional argument.. Classiquement, les "options" sont les jetons comme --recursivequi peuvent apparaître dans n'importe quel ordre, ou même être combinés ensemble sous leur forme courte, comme avec rm -rf. Au contraire, les "arguments positionnels" sont beaucoup plus comme des arguments passés à une fonction dans un langage de programmation: leur position dans la liste des jetons définit exactement ce que le programme va en faire (ce sont souvent des noms de fichiers). --supprime l'ambiguïté quant à ce qui est lequel.
iono
42

Pour revenir en amont / maître, procédez comme suit:

git checkout upstream/master -- myfile.txt
Ann Raiho
la source
19

Depuis Git 2.23 (août 2019), vous pouvez utiliser restore( plus d'informations ):

git restore pathTo/MyFile

Ce qui précède sera restauré MyFilele HEAD(le dernier commit) sur la branche actuelle.

Si vous souhaitez obtenir les modifications d'autres validations, vous pouvez revenir en arrière dans l'historique des validations. La commande ci-dessous obtiendra MyFiledeux validations avant la dernière. Vous avez maintenant besoin de l' option -s( --source) puisque vous utilisez maintenant master~2et non master(par défaut) lorsque vous restaurez la source:

git restore -s master~2 pathTo/MyFile

Vous pouvez également obtenir le fichier d'une autre branche!

git restore -s my-feature-branch pathTo/MyFile
AxeEffect
la source
1
Le moyen le plus simple jusqu'à présent. Malheureusement, cette réponse ne reçoit pas suffisamment d'attention.
singrium
5

La référence à HEAD n'est pas nécessaire.

git checkout -- file.js est suffisant

Emanuel Friedrich
la source
4

vous pouvez utiliser la commande ci-dessous pour réinitialiser un seul fichier

git checkout HEAD -- path_to_file/file_name

Liste tous les fichiers modifiés à obtenir path_to_file/filenameavec la commande ci-dessous

git status
HariKishore
la source
1

Vous pouvez utiliser la commande suivante:

git reset -- my-file.txt

qui mettra à jour à la fois la copie de travail de l' my-file.txtajout.

ADDYQU
la source
Ne modifie pas le contenu du fichier modifié, comme demandé.
Rafael
Lorsque vous ajoutez à la cachette Avez-vous modifié le fichier?
ADDYQU
1
Ce n'est pas précisément le point @ADDQU. La question est de savoir comment "réinitialiser matériellement" un fichier, et non le supprimer de la liste intermédiaire.
Rafael
@Rafael Vous avez raison, mais je veux vous faire savoir qu'il existe également un moyen.
ADDYQU
0

Vous pouvez utiliser la commande suivante:

git checkout filename

Si vous avez une branche avec le même nom de fichier, vous devez utiliser cette commande:

git checkout -- filename
Milad Rahimi
la source
1
Cela ne "réinitialise pas dur" le fichier - il copie uniquement l'état de l'index dans l'arborescence de travail. Une "réinitialisation matérielle" réinitialiserait d'abord l'index.
AH
-21

Un moyen simple, facile et pratique de vous sortir de l'eau chaude, surtout si vous n'êtes pas si à l'aise avec git:

  1. Afficher le journal de votre fichier

    git log myFile.js

    commit 1023057173029091u23f01w276931f7f42595f84f Auteur: kmiklas Date: mar 7 août 09:29:34 2018 -0400

    JIRA-12345 - Refactor avec une nouvelle architecture.

  2. Notez le hachage du fichier:

    1023057173029091u23f01w276931f7f42595f84f

  3. Affichez le fichier à l'aide du hachage. Assurez-vous que c'est ce que vous voulez:

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ myFile.js

  4. Rediriger le fichier vers une copie locale

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ monFichier.js> monFichier.07aug2018.js

  5. Sauvegardez votre fichier actuel.

    cp myFile.js myFile.bak.js

  6. Ouvrez les deux fichiers dans votre éditeur de texte préféré.

    vim myFile.js
    vim myFile.07aug2018.js

  7. Copiez le code n 'paste de myFile.07aug2018.js vers myFile.js et enregistrez.

  8. Validez et envoyez myFile.js

  9. Consultez à nouveau le journal et confirmez que votre fichier est correctement en place.

  10. Dites à vos clients de tirer la dernière version, regardez-la avec plaisir avec l'ancienne version en place.

Pas la solution la plus sexy ou la plus git-centrique, et certainement une réinitialisation / réversion "manuelle", mais cela fonctionne. Il nécessite une connaissance minimale de git et ne perturbe pas l'historique des validations.

kmiklas
la source
2
Cette réponse est beaucoup plus complexe et sujette aux erreurs que toutes les solutions qui la précèdent de plusieurs années.
Artif3x
2
Pourquoi devrait-on utiliser cette solution!? la vraie réponse n'est qu'une simple commande.
Milad Rahimi du
1
Il s'agit de la solution optimale pour certaines circonstances. Il a du mérite pour ceux qui sont dans une impasse, où git fonctionne mal, et pour ceux qui ont besoin d'une solution de contournement.
kmiklas