Come fare un git diff su file spostato / rinominato?


128

Ho spostato un file usando git mv. Ora vorrei fare una differenza sul nuovo file per confrontarlo con il vecchio file (con il vecchio nome, ora inesistente).

Come faccio a fare questo?


4
Presto (git 2.9, giugno 2016), git diff -- yourRenamedFilesarà sufficiente una semplice . Vedi la mia risposta qui sotto
VonC

Risposte:


145

Devi usare -M per consentire a git di rilevare automaticamente il file spostato durante il diffing. Usare esattamente git diffcome menzionato Knittl non funziona per me.

Quindi semplicemente: git diff -Mdovrebbe farlo.

La documentazione per questo switch è:

-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.

7
Salvavita! Le mie differenze git ora sono molto meglio. 1) È sicuro usare sempre questa opzione? 2) Posso aggiungere questa opzione come comportamento predefinito al mio ~/.gitconfig?
Kevinevpe,

5
Si noti che il rilevamento della ridenominazione funziona solo quando nella raccolta dei file elaborati compaiono sia i file vecchi che quelli nuovi git diff. L'esecuzione git diff -Msu un singolo file (rinominato) non segnala una ridenominazione.
Leon,

1
Questo non funziona per me, ma git log --follow -- file_after_move.txtfunziona bene. Mostra l'intera storia, anche prima del trasloco. Qualche idea? Sto correndo git version 2.11.0.windows.1.
Bouvierr

1
L' -Copzione per il rilevamento di copie è utile e simile. L'ho usato -Mper guardare un diff dove avevo refactored un file in due (senza nessun nome corrispondente all'originale).
cp.engr

85

Oltre a ciò che ha scritto Knittl , puoi sempre usare:

git diff HEAD:./oldfilename newfilename

dove HEAD:./oldfilenamesignifica oldfilename nell'ultimo commit (in HEAD), relativo alla directory corrente.

Se non hai abbastanza nuovo git, dovresti usare invece:

git diff HEAD:path/to/oldfilename newfilename

8
Grazie per questo. È inoltre possibile specificare una specifica commettere invece di testa, vale a diregit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom

8
Nel caso in cui non sia chiaro, puoi anche specificare i nomi dei rami o qualsiasi altro riferimento, come ad esempio:git diff branch:old/filen.name newfilename
jricher

Il primo modulo funziona per me, se si cdnella directory e non si aggiunge --prima della commit:pathcoppia. Git sembra essere molto esigente con la sintassi qui.
dhardy,

1
@dhardy La <commit-ish>:<pathname>sintassi è un identificatore di oggetto, qualcosa di Git-ish; dopo che --Git si aspetta solo nomi di file.
Jakub Narębski,

18

Con git 2.9 (giugno 2016), non dovrai -Mpiù aggiungere . git diffutilizza -Mper impostazione predefinita.

Vedi commit 5404c11 , commit 9501d19 , commit a9276a6 , commit f07fc9e , commit 62df1e6 (25 febbraio 2016) di Matthieu Moy ( moy) .
(Unita da Junio ​​C Hamano - gitster- in commit 5d2a30d , 03 apr 2016)

diff: attiva diff.renamesdi default

Rinomina il rilevamento è una funzionalità molto conveniente e i nuovi utenti non dovrebbero scavare nella documentazione per trarne vantaggio.

Le potenziali obiezioni all'attivazione del rilevamento della ridenominazione sono che a volte fallisce ed a volte è lento. Ma il rilevamento della ridenominazione è già attivato di default in diversi casi come " git status" e " git merge", quindi l'attivazione diff.renamesnon cambia sostanzialmente la situazione. Quando il rilevamento della ridenominazione fallisce, ora fallisce costantemente tra " git diff" e " git status".

Questa impostazione non influisce sui comandi idraulici, quindi gli script ben scritti non saranno interessati.

I nuovi test per questa funzione sono qui .


1

git diff -Mattiva il rilevamento della ridenominazione come altri hanno già detto (e come sottolineato da @VonC, è attivato di default da git 2.9). Ma se si dispone di un grosso changeset, il rilevamento inesatto di ridenominazione potrebbe essere disattivato di nuovo. Git visualizzerà un avviso come il seguente, che è facile perdere tra le differenze che stai visualizzando:

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.

In tal caso, impostare l'opzione di configurazione come suggerito da git, ad esempio

git config diff.renamelimit 450

e riesegui il tuo comando diff.


0

Per qualsiasi motivo l'utilizzo HEAD:./oldfilename(o il percorso assoluto) non ha funzionato per me, ma HEAD:oldfilename(grazie cmn):

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

HTH


Forse il tuo idiota è troppo vecchio per capire HEAD:./oldfilename?
Jakub Narębski

-4

semplicemente eseguire git diffsenza argomenti, o git diff -- newfilename. git è abbastanza intelligente da confrontare i giusti file / contenuti (ad es. contenuto originale prima di rinominare con contenuto alterato dopo rinominare)


2
git non è assolutamente abbastanza intelligente nella maggior parte dei casi. Il semplice git mvinserimento di un singolo file e quindi il confronto dello stato di gestione temporanea con un altro ramo altrimenti identico produrrà il diff "tutto è stato eliminato e ricreato di nuovo" a meno che non -Mvenga utilizzato.
Reinderien,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.