¿Cómo hacer un git diff en un archivo movido / renombrado?

128

Moví un archivo usando git mv. Ahora me gustaría hacer una diferencia en el nuevo archivo para compararlo con el archivo antiguo (con el nombre antiguo, ahora inexistente).

¿Cómo hago esto?

Dr. Jerry
fuente
44
Pronto (git 2.9, junio de 2016), un simple git diff -- yourRenamedFileserá suficiente. Vea mi respuesta a continuación
VonC

Respuestas:

145

Debe usar -M para permitir que git detecte automáticamente el archivo movido cuando difiera. Usando sologit diff como knittl mencionado no funciona para mí.

Así que simplemente: git diff -Mdebería hacerlo.

La documentación para este cambio es:

-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
fuente
77
¡Salvador de la vida! Mis diferencias de git son mucho mejores ahora. 1) ¿Es seguro usar siempre esta opción? 2) ¿Puedo agregar esta opción como comportamiento predeterminado a mi ~/.gitconfig?
kevinarpe
55
Tenga en cuenta que la detección de cambio de nombre solo funciona cuando aparecen archivos antiguos y nuevos en la colección de archivos procesados ​​por git diff. La ejecución git diff -Men un solo archivo (renombrado) no informa un cambio de nombre.
Leon
1
Esto no funciona para mí, pero git log --follow -- file_after_move.txtfunciona bien. Muestra toda la historia, incluso antes de la mudanza. ¿Algunas ideas? Estoy funcionando git version 2.11.0.windows.1.
bouvierr
1
La -Copción para detectar copias es útil y similar. Lo usé -Mpara mirar una diferencia donde había refactorizado un archivo en dos (sin que ninguno de los nombres coincida con el original).
cp.engr
85

Además de lo que knittl escribió , siempre puedes usar:

git diff HEAD:./oldfilename newfilename

donde HEAD:./oldfilenamesignifica oldfilename en el último commit (en HEAD), relativo al directorio actual.

Si no tienes git lo suficientemente nuevo, deberías usar en su lugar:

git diff HEAD:path/to/oldfilename newfilename
Jakub Narębski
fuente
8
Gracias por esto. También puede especificar un commit específico en lugar de head, es decirgit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom
8
En caso de que no esté claro, también puede especificar nombres de sucursales o cualquier otra referencia, como:git diff branch:old/filen.name newfilename
jricher
El primer formulario funciona para mí, si va cdal directorio y no agrega --antes del commit:pathpar. Git parece ser muy exigente con la sintaxis aquí.
Dhardy
1
@dhardy La <commit-ish>:<pathname>sintaxis es un identificador de objeto, algo Git-ish; después de que --Git solo espera nombres de archivo.
Jakub Narębski
18

Con git 2.9 (junio de 2016), no tendrá que agregar -Mmás. git diffutiliza -Mpor defecto.

Ver commit 5404c11 , commit 9501d19 , commit a9276a6 , commit f07fc9e , commit 62df1e6 (25 de febrero de 2016) por Matthieu Moy ( moy) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 5d2a30d , 03 abr 2016)

diff: activar diff.renamespor defecto

La detección de cambio de nombre es una característica muy conveniente, y los nuevos usuarios no deberían tener que buscar en la documentación para beneficiarse de ella.

Las posibles objeciones a la activación de la detección de cambio de nombre son que a veces falla y a veces es lenta. Pero la detección de cambio de nombre ya está activada por defecto en varios casos como " git status" y " git merge", por lo que la activación diff.renamesno cambia la situación de manera fundamental. Cuando falla la detección de cambio de nombre, ahora falla constantemente entre " git diff" y " git status".

Esta configuración no afecta los comandos de plomería, por lo tanto, los scripts bien escritos no se verán afectados.

Las nuevas pruebas para esta función están aquí .

VonC
fuente
1

git diff -Mactiva la detección de cambio de nombre como han dicho otros (y como señaló @VonC, se activa por defecto desde git 2.9). Pero si tiene un conjunto de cambios grande, la detección inexacta de cambio de nombre aún puede desactivarse nuevamente. Git mostrará una advertencia como la siguiente, que es fácil pasar por alto en medio de la diferencia que está viendo:

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.

En ese caso, configure la opción de configuración como sugiere git, por ejemplo

git config diff.renamelimit 450

y vuelva a ejecutar su comando diff.

mindriot
fuente
0

Por alguna razón, usar HEAD:./oldfilename(o ruta absoluta) no funcionó para mí, pero HEAD:oldfilenamesí (gracias cmn):

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

HTH

Oli Studholme
fuente
¿Quizás tu tonto es demasiado viejo para entenderlo HEAD:./oldfilename?
Jakub Narębski
-4

simplemente ejecute git diffsin ningún argumento, o git diff -- newfilename. git es lo suficientemente inteligente como para comparar los archivos / contenidos correctos (es decir, contenido original antes de cambiar el nombre con contenido alterado después de cambiar el nombre)

knittl
fuente
2
git no es lo suficientemente inteligente en la mayoría de los casos. Simplemente git mvcon un solo archivo y luego comparando el estado por etapas con otra rama idéntica producirá el diferencial "todo fue eliminado y recreado de nuevo" a menos que -Mse use.
Reinderien