Wie mache ich ein Git-Diff für verschobene / umbenannte Dateien?

128

Ich habe eine Datei mit verschoben git mv . Jetzt möchte ich einen Unterschied für die neue Datei machen, um sie mit der alten Datei zu vergleichen (mit dem alten, jetzt nicht existierenden Namen).

Wie mache ich das?

Dr. Jerry
quelle
4
Bald (Git 2.9, Juni 2016) wird ein einfaches git diff -- yourRenamedFileausreichen. Siehe meine Antwort unten
VonC

Antworten:

145

Sie müssen -M verwenden, damit git die verschobene Datei beim Unterschieden automatisch erkennt. Mit justgit diff von Knittl funktioniert bei mir nicht.

Also einfach: git diff -Msollte es tun.

Die Dokumentation für diesen Schalter lautet:

-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
quelle
7
Lebensretter! Meine Git-Unterschiede sind jetzt so viel besser. 1) Ist es sicher, diese Option immer zu verwenden? 2) Kann ich diese Option als Standardverhalten zu meinem hinzufügen ~/.gitconfig?
Kevinarpe
5
Beachten Sie, dass die Umbenennungserkennung nur funktioniert, wenn sowohl alte als auch neue Dateien in der Sammlung der von verarbeiteten Dateien angezeigt werden git diff. Das Ausführen git diff -Meiner einzelnen (umbenannten) Datei meldet keine Umbenennung.
Leon
1
Das funktioniert bei mir nicht, git log --follow -- file_after_move.txtfunktioniert aber gut. Es zeigt die gesamte Geschichte, auch vor dem Umzug. Irgendwelche Ideen? Ich renne git version 2.11.0.windows.1.
Bouvierr
1
Die -COption zum Erkennen von Kopien ist nützlich und ähnlich. Ich habe es verwendet -M, um einen Diff zu betrachten, bei dem ich eine Datei in zwei umgestaltet hatte (wobei keiner der Namen mit dem Original übereinstimmt).
cp.engr
85

Zusätzlich zu dem, was knittl geschrieben hat , können Sie immer Folgendes verwenden:

git diff HEAD:./oldfilename newfilename

Dabei HEAD:./oldfilenamebedeutet alter Dateiname im letzten Commit (in HEAD) relativ zum aktuellen Verzeichnis.

Wenn Sie nicht genug neues Git haben, müssten Sie stattdessen verwenden:

git diff HEAD:path/to/oldfilename newfilename
Jakub Narębski
quelle
8
Danke dafür. Sie können auch ein bestimmtes Commit anstelle von head angeben, dhgit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom
8
Falls es unklar ist, können Sie auch git diff branch:old/filen.name newfilename
Zweignamen
Das erste Formular funktioniert für mich, wenn Sie cdin das Verzeichnis und nicht --vor dem commit:pathPaar hinzufügen . Git scheint hier mit der Syntax sehr wählerisch zu sein.
Dhardy
1
@dhardy Die <commit-ish>:<pathname>Syntax ist eine Objektkennung, etwas Git-ish; nachdem --Git nur Dateinamen erwartet.
Jakub Narębski
18

Mit Git 2.9 (Juni 2016) müssen Sie nichts mehr hinzufügen -M. git diffVerwendet-M standardmäßig.

Siehe Commit 5404c11 , Commit 9501d19 , Commit a9276a6 , Commit f07fc9e , Commit 62df1e6 (25. Februar 2016) von Matthieu Moy ( moy) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 5d2a30d , 03. April 2016)

diff: diff.renamesstandardmäßig aktivieren

Die Umbenennungserkennung ist eine sehr praktische Funktion, und neue Benutzer sollten nicht in der Dokumentation stöbern müssen, um davon zu profitieren.

Mögliche Einwände gegen die Aktivierung der Umbenennungserkennung sind, dass sie manchmal fehlschlägt und manchmal langsam ist. Die Umbenennungserkennung ist jedoch in einigen Fällen wie " git status" und " git merge" bereits standardmäßig aktiviert , sodass durch das Aktivieren diff.renamesdie Situation nicht grundlegend geändert wird. Wenn die Umbenennungserkennung fehlschlägt, schlägt sie jetzt konsistent zwischen " git diff" und " git status" fehl .

Diese Einstellung wirkt sich nicht auf Installationsbefehle aus, daher sind gut geschriebene Skripte nicht betroffen.

Die neuen Tests für diese Funktion sind hier .

VonC
quelle
1

git diff -MAktiviert die Umbenennungserkennung, wie andere gesagt haben (und wie @VonC hervorhob, ist sie ab Git 2.9 standardmäßig aktiviert). Wenn Sie jedoch einen großen Änderungssatz haben, wird die Erkennung ungenauer Umbenennungen möglicherweise immer noch deaktiviert. Git zeigt eine Warnung wie die folgende an, die im angezeigten Diff leicht zu übersehen ist:

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.

Stellen Sie in diesem Fall die Konfigurationsoption beispielsweise wie von git vorgeschlagen ein

git config diff.renamelimit 450

und führen Sie Ihren diff-Befehl erneut aus.

Mindriot
quelle
0

Aus irgendeinem Grund hat die Verwendung HEAD:./oldfilename(oder der absolute Pfad) bei mir nicht funktioniert, aber HEAD:oldfilename(danke cmn):

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

HTH

Oli Studholme
quelle
Vielleicht ist dein Idiot zu alt, um es zu verstehen HEAD:./oldfilename?
Jakub Narębski
-4

einfach git diffohne Argumente ausführen , oder git diff -- newfilename. git ist klug genug, um die richtigen Dateien / Inhalte zu vergleichen (dh den ursprünglichen Inhalt vor dem Umbenennen mit dem geänderten Inhalt nach dem Umbenennen).

stricken
quelle
2
Git ist in den meisten Fällen absolut nicht klug genug. Wenn git mvSie einfach eine einzelne Datei erstellen und dann den bereitgestellten Status mit einem anderen ansonsten identischen Zweig vergleichen, wird der Unterschied "Alles wurde gelöscht und neu erstellt" erzeugt, sofern er nicht -Mverwendet wird.
Reinderien