git diff file contre son dernier changement

236

Est-il possible d'obtenir que git produise un diff entre un fichier spécifique tel qu'il existe maintenant et tel qu'il existait avant le dernier commit qui l'a changé?

Autrement dit, si nous savons:

$ git log --oneline myfile
123abc Fix some stuff
456def Frobble the foos
789dba Initial commit

git diff 456def myfileAffiche ensuite la dernière modification de mon fichier. Il est possible de faire de même sans les connaissances produites par le git log; qu'est-ce qui a changé dans 123abc?

Chowlett
la source
8
Je préfère utilisergit diff HEAD^ <file_path>
asgs
4
@asgs - Ne fait pas ce que je demandais (pour deux raisons - HEAD^est 123abc, HEAD^^est 456def; et s'il y avait d'autres commits qui n'ont pas affecté ce fichier, il y HEAD^fait référence)
Chowlett
Vous avez raison, vous avez manqué la partie "le dernier commit qui a changé"
asgs

Réponses:

216

Cela existe, mais c'est en fait une caractéristique de git log:

git log -p [--follow] [-1] <path>

Notez que -ppeut également être utilisé pour afficher la différence en ligne à partir d'un seul commit:

git log -p -1 <commit>

Options utilisées:

  • -p(également -uou --patch) est masqué deeeeeeeep dans la git-logpage de manuel et est en fait une option d'affichage pour git-diff. Lorsqu'il est utilisé avec log, il affiche le correctif qui serait généré pour chaque validation , ainsi que les informations de validation, et masque les validations qui ne touchent pas le spécifié <path>. (Ce comportement est décrit dans le paragraphe sur --full-diff, ce qui provoque l'affichage du diff complet de chaque commit.)
  • -1affiche uniquement la modification la plus récente du fichier spécifié ( -n 1peut être utilisé à la place de -1); sinon, toutes les différences non nulles de ce fichier sont affichées.
  • --follow est requis pour voir les changements survenus avant un changement de nom.

Pour autant que je sache, c'est le seul moyen de voir immédiatement le dernier ensemble de modifications apportées à un fichier sans utiliser git log(ou similaire) pour compter le nombre de révisions intermédiaires ou déterminer le hachage du commit.

Pour voir les modifications de révisions plus anciennes, faites simplement défiler le journal ou spécifiez une validation ou une balise à partir de laquelle démarrer le journal. (Bien sûr, la spécification d'une validation ou d'une balise vous ramène au problème d'origine de déterminer quelle est la bonne validation ou la bonne balise.)

Crédit lorsque le crédit est dû:

  • J'ai découvert log -pgrâce à cette réponse .
  • Nous remercions FranciscoPuga et cette réponse de m'avoir montré l' --followoption.
  • Nous remercions ChrisBetti d'avoir mentionné l' -n 1option et atatko d'avoir mentionné la -1variante.
  • Nous remercions sweaver2112 de m'avoir permis de lire la documentation et de comprendre ce que -p«signifie» sémantiquement.
Kyle Strand
la source
6
C'était une excellente solution pour moi. A montré chaque commit et ses différences avec le fichier actuel lorsque j'ai courugit log -p filename
Ian Jamieson
4
Parfait. Pour voir juste le dernier changement, c'est aussi simple que d'ajouter le -n 1paramètre. git log -p -n 1 filename
Chris Betti
@ChrisBetti Merci; J'ai intégré cela dans ma réponse!
Kyle Strand du
1
-n 1peut également être remplacé par -1, cela ne change pas le résultat je préfère juste la syntaxe:git log -p -1 filename
atatko
1
il existe une option utile "--skip = [n]". Vous pouvez taper git log -p -1 --skip=1 <path>pour afficher le deuxième commit.
Maciek Łoziński
220

L'une des façons d'utiliser git diff est:

git diff <commit> <path>

Et une façon courante de référencer un commit du dernier commit est un chemin relatif vers le HEAD réel. Vous pouvez référencer les validations précédentes comme HEAD ^ (dans votre exemple, ce sera 123abc) ou HEAD ^^ (456def dans votre exemple), etc ...

La réponse à votre question est donc:

git diff HEAD^^ myfile
Francisco Puga
la source
6
Oh bien sûr. J'ai essayé HEAD^, mais bien sûr, cela n'a rien produit. Je n'ai pas pensé à essayer HEAD^^.
Chowlett
17
Peut-être une syntaxe plus facile pour les commits de longue date:HEAD~2
ibizaman
19
Ce n'est pas vrai (au moins pour Git 1.9.0) qui HEAD^^ myfilefera réellement référence à l'avant-dernier commit qui a changé myfile; il fera référence à l'avant-dernier commit global. Existe-t-il un moyen de spécifier «Je veux voir la dernière modification apportée à ce fichier» sans spécifier (une partie de) le hachage de validation ou compter le nombre de validations entre la dernière modification apportée à ce fichier et la révision actuelle?
Kyle Strand
3
Hm, on dirait que git log -pc'est assez proche.
Kyle Strand
30
raison du downvote: la question demande "entre un fichier spécifique tel qu'il existe maintenant et tel qu'il existait avant le dernier commit qui l'a changé ", mais si le fichier n'a pas été modifié lors du dernier commit global, cette réponse ne fonctionne pas.
Chris Betti
8

Si vous êtes bien en utilisant un outil graphique, cela fonctionne très bien:

gitk <file>

gitk affiche maintenant toutes les validations où le fichier a été mis à jour. Marquer un commit vous montrera le diff par rapport au commit précédent dans la liste. Cela fonctionne également pour les répertoires, mais vous pouvez également sélectionner le fichier à différencier pour le commit sélectionné. Super utile!

Martin G
la source
1
Aussi très utile: git difftool HEAD^ fileougit difftool -d HEAD^ path
ForeverLearning