Annuler les modifications apportées à un fichier dans un commit

126

Je souhaite annuler les modifications apportées par un commit particulier à un fichier donné uniquement.

Puis-je utiliser la commande git revert pour cela?

Une autre façon simple de le faire?

Lakshman Prasad
la source
Etrange ... pourquoi ce changement après toutes ces années?
VonC le

Réponses:

222

La façon la plus propre que j'ai vue de faire cela est décrite ici

git show some_commit_sha1 -- some_file.c | git apply -R

Similaire à la réponse de VonC mais en utilisant git showet git apply.

mgalgs
la source
10
Bien fait. La solution de script est excessive pour cela. Pourquoi ne peut-il pas simplement y avoir git revert nom de fichier sha-1?
Mark Edington
16
Cela fonctionne sur mon Mac, mais sur Windows (sous Cygwin) cela me donne:fatal: unrecognized input
Kedar Mhaswade
1
@MerhawiFissehaye: Je pense que git checkout ne fera que revenir sur les modifications pour revenir à l'état qui était dans commit. J'ai fait 'git add filename; git commit --amend 'pour supprimer le fichier de commit.
ViFI
3
Juste un conseil, je dois presque toujours ajouter le -3drapeau à git apply pour la fusion à trois lorsque le correctif échoue, car je corrige généralement un changement un peu en arrière.
angularsen
2
Peut-être évident pour la plupart, mais assurez-vous qu'il some_file.cinclut le chemin d' accès au fichier s'il y en a un, sinon vous ne corrigerez rien en silence :)
Warpling
35

En supposant que vous pouvez modifier l'historique des validations, voici un flux de travail pour annuler les modifications d'un seul fichier lors d'un commit précédent:

Par exemple, vous souhaitez annuler les modifications dans 1 fichier ( badfile.txt) dans la validation aaa222:

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

Rebase sur le commit de base, modifie le commit du problème et continue.

1) Démarrez le rebase interactif:

git rebase -i aaa111

2) Marquez la validation du problème pour édition dans l'éditeur en changeant picken e(pour édition):

e aaa222
pick aaa333

3) Annulez les modifications apportées au mauvais fichier:

git show -- badfile.txt | git apply -R

4) Ajoutez les changements et modifiez le commit:

git add badfile.txt
git commit --amend

5) Terminez le rebase:

git rebase --continue
tee
la source
Je veux juste souligner que cela suppose que vous pouvez modifier l'historique de git. Certaines réponses ci-dessus créent un nouveau commit qui annule le changement particulier sans modifier l'historique, ce qui n'est pas toujours possible / autorisé.
angularsen
Fantastique. C'était exactement ce que je cherchais. J'avais déjà cette idée, mais j'étais confus en faisant le rebase interactif que les fichiers lors de la réalisation du editne montraient pas comme modifiés. Mais le a git show -- badfile.txt | git apply -Rdonné la réponse dont j'avais besoin <3
mraxus
si je comprends ce git apply -R supprime le commit sur ce fichier en le remettant à l'état modifié d'origine?
Du
19

git revert est pour tout le contenu de fichier dans un commits.

Pour un seul fichier, vous pouvez le script :

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

(Depuis les utilitaires git-shell-scripts de smtlaissezfaire )


Remarque:

une autre méthode est décrite ici si vous n'avez pas encore validé votre modification actuelle.

git checkout -- filename

git checkout a quelques options pour un fichier, modifiant le fichier de HEAD, écrasant votre changement.


Dropped.on.Caprica mentionne dans les commentaires :

Vous pouvez ajouter un alias à git pour pouvoir le faire git revert-file <hash> <file-loc>et faire revenir ce fichier spécifique.
Voir l'essentiel .

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh
VonC
la source
Juste pour ajouter à la discussion ici, vous pouvez ajouter un alias à git afin que vous puissiez le faire git revert-file <hash> <file-loc>et que ce fichier spécifique soit rétabli. J'ai soulevé cette réponse (même si j'ai dû faire quelques modifications pour fonctionner correctement). Vous pouvez trouver une copie de mon .gitconfigscript édité ici: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
AlbertEngelB
@ Dropped.on.Caprica bon point. Je l'ai inclus dans la réponse pour plus de visibilité.
VonC le
12

J'utiliserais simplement l' --no-commitoption pour git-revert, puis supprimerais les fichiers que vous ne voulez pas récupérer de l'index avant de finalement le valider. Voici un exemple montrant comment annuler facilement les modifications apportées à foo.c dans le deuxième commit le plus récent:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

Le premier git-reset"désactive" tous les fichiers, de sorte que nous puissions ensuite rajouter uniquement le fichier que nous voulons restaurer. La finale git-reset --hardsupprime les fichiers restants que nous ne voulons pas conserver.

Moulage Dan
la source
9

Beaucoup plus simple:

git reset HEAD^ path/to/file/to/revert

puis

git commit --amend   

puis

git push -f

le fichier est parti et la validation du hachage, du message, etc. est identique.

Forrest
la source
Pour être complet, avez-vous besoin d'une git checkout -- path/to/file/to/revertétape? De plus, ce n'est pas vrai que le hachage est le même après coup, non? La dernière phrase pourrait être meilleure comme quelque chose comme: "Le résultat est que le dernier commit est remplacé par un nouveau qui diffère uniquement en ce qu'il ne contient pas les modifications du fichier rétabli."
Kevin
@Kevin vous avez probablement raison. Je vais devoir vérifier cette dernière ligne, mais en y repensant il y a quelques années, je serais surpris si le hachage de validation est inchangé.
Forrest
6
git reset HEAD^ path/to/file/to/revert/in/commit

La commande ci-dessus retirera le fichier de la validation, mais elle se reflétera dans git status.

git checkout path/to/file/to/revert/in/commit

La commande ci-dessus annulera les modifications (en conséquence, vous obtenez le même fichier que HEAD).

git commit

(Passer --amendpour modifier le commit.)

git push

Avec cela, le fichier qui est déjà dans le commit est supprimé et restauré.

Les étapes ci-dessus doivent être suivies à partir de la branche où la validation est effectuée.

Bharat TS
la source
5

Vous pouvez suivre cette procédure:

  1. git revert -n <*commit*>( -nannuler toutes les modifications mais ne les validera pas)
  2. git add <*filename*> (nom du / des fichier / s que vous souhaitez rétablir et valider)
  3. git commit -m 'reverted message' (ajouter un message pour revenir)
  4. après la validation, supprimez les autres modifications de fichiers afin que les fichiers restent à jour avec les modifications que vous avez validées avant le retour
Imran Sahil
la source
1

Si vous souhaitez réinitialiser les modifications sur un fichier de votre dernier commit, c'est ce que j'utilise habituellement. Je pense que c'est la solution la plus simple.

Veuillez noter que le fichier sera ajouté à la zone de préparation.

git checkout <prev_commit_hash> -- <path_to_your_file>

J'espère que ça aide :)

Gabeeka
la source