Comment faire un git diff sur un fichier déplacé / renommé?

128

J'ai déplacé un fichier en utilisant git mv. Maintenant, je voudrais faire un diff sur le nouveau fichier pour le comparer avec l'ancien fichier (avec l'ancien nom maintenant inexistant).

Comment puis-je faire cela?

dr jerry
la source
4
Bientôt (git 2.9, juin 2016), un simple git diff -- yourRenamedFilesuffira. Voir ma réponse ci
VonC

Réponses:

145

Vous devez utiliser -M pour laisser git détecter automatiquement le fichier déplacé en cas de différence. Utiliser tout git diffcomme knittl mentionné ne fonctionne pas pour moi.

Si simplement: git diff -Mdevrait le faire.

La documentation de ce commutateur est:

-M[<n>], --find-renames[=<n>]
       Detect renames. If n is specified, it is a threshold on the similarity index 
       (i.e. amount of addition/deletions compared to the file’s size). For example, 
       -M90% means git should consider a delete/add pair to be a rename if more than
       90% of the file hasn’t changed.
Zitrax
la source
7
Gareautrain! Mes différences git sont tellement meilleures maintenant. 1) Est-il sûr de toujours utiliser cette option? 2) Puis-je ajouter cette option comme comportement par défaut à mon ~/.gitconfig?
kevinarpe
5
Notez que la détection de changement de nom ne fonctionne que lorsque les anciens et les nouveaux fichiers apparaissent dans la collection de fichiers traités par git diff. L'exécution git diff -Msur un seul fichier (renommé) ne signale pas un changement de nom.
Leon
1
Cela ne fonctionne pas pour moi, mais git log --follow -- file_after_move.txtfonctionne bien. Il montre toute l'histoire, y compris avant le déménagement. Des idées? Je cours git version 2.11.0.windows.1.
bouvierr
1
L' -Coption de détection des copies est utile et similaire. Je l'ai utilisé avec -Mpour regarder un diff où j'avais refactoré un fichier en deux (sans aucun nom correspondant à l'original).
cp.engr
85

En plus de ce que knittl a écrit , vous pouvez toujours utiliser:

git diff HEAD:./oldfilename newfilename

HEAD:./oldfilenamesignifie ancien nom de fichier dans le dernier commit (dans HEAD), par rapport au répertoire courant.

Si vous n'avez pas assez de nouveau git, vous devrez utiliser à la place:

git diff HEAD:path/to/oldfilename newfilename
Jakub Narębski
la source
8
Merci pour cela. Vous pouvez également spécifier un commit spécifique au lieu de head, c'estgit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom
8
En cas de doute, vous pouvez également spécifier les noms des succursales ou toute autre référence, telle que:git diff branch:old/filen.name newfilename
jricher
Le premier formulaire fonctionne pour moi, si vous cddans le répertoire et ne l'ajoutez pas --avant la commit:pathpaire. Git semble être très pointilleux avec la syntaxe ici.
dhardy
1
@dhardy La <commit-ish>:<pathname>syntaxe est un identifiant d'objet, quelque chose de Git-ish; après que --Git n'attend que les noms de fichiers.
Jakub Narębski
18

Avec git 2.9 (juin 2016), vous n'aurez plus à en ajouter -M. git diffutilise -Mpar défaut.

Voir commit 5404c11 , commit 9501d19 , commit a9276a6 , commit f07fc9e , commit 62df1e6 (25 février 2016) par Matthieu Moy ( moy) .
(Fusionné par Junio ​​C Hamano - gitster- in commit 5d2a30d , 03 avril 2016)

diff: activer diff.renamespar défaut

La détection de changement de nom est une fonctionnalité très pratique et les nouveaux utilisateurs ne devraient pas avoir à fouiller dans la documentation pour en bénéficier.

Les objections potentielles à l'activation de la détection de changement de nom sont qu'elle échoue parfois et qu'elle est parfois lente. Mais la détection de renommage est déjà activée par défaut dans plusieurs cas comme " git status" et " git merge", donc l'activation diff.renamesne change pas fondamentalement la situation. Lorsque la détection de changement de nom échoue, elle échoue désormais systématiquement entre " git diff" et " git status".

Ce paramètre n'affecte pas les commandes de plomberie, par conséquent les scripts bien écrits ne seront pas affectés.

Les nouveaux tests pour cette fonctionnalité sont ici .

VonC
la source
1

git diff -Mactive la détection de renommage comme d'autres l'ont dit (et comme @VonC l'a souligné, elle est activée par défaut à partir de git 2.9). Mais si vous avez un grand ensemble de modifications, la détection de changement de nom inexacte peut toujours être désactivée. Git affichera un avertissement comme celui-ci, qui est facile à manquer parmi les différences que vous visualisez:

warning: inexact rename detection was skipped due to too many files.
warning: you may want to set your diff.renameLimit variable to at least 450 and retry the command.

Dans ce cas, définissez l'option de configuration comme suggéré par git, par exemple

git config diff.renamelimit 450

et réexécutez votre commande diff.

mindriot
la source
0

Pour une raison quelconque, l'utilisation HEAD:./oldfilename(ou le chemin absolu) n'a pas fonctionné pour moi, mais HEAD:oldfilenamea fonctionné (merci cmn):

git diff HEAD:oldfilename newfilename
git diff 2a80f45:oldfilename f65f3b3:newfilename

HTH

Oli Studholme
la source
Peut-être que votre connard est trop vieux pour comprendre HEAD:./oldfilename?
Jakub Narębski
-4

exécutez simplement git diffsans aucun argument, ou git diff -- newfilename. git est suffisamment intelligent pour comparer les bons fichiers / contenus (c'est-à-dire le contenu original avant le changement de nom avec le contenu modifié après le changement de nom)

tricot
la source
2
git n'est absolument pas assez intelligent dans la plupart des cas. Le simple fait d' git mvingérer un seul fichier et de comparer ensuite l'état par étapes à une autre branche par ailleurs identique produira le diff "tout a été supprimé et recréé" à moins qu'il ne -Msoit utilisé.
Reinderien