git dif renombró / movió y modificó los files, pero saltó los files renombrados / movidos e idénticos

Estoy usando:

git diff HEAD --diff-filter=R -M 

con la herramienta de fusión externa meld para mostrar los files que han sido renombrados / movidos y modificados. Siempre hago un git diff antes de comprometerme a verificar mi trabajo y ensamblar correctamente el post de confirmación. Muchas veces renombraré / moveré files, lo que también requerirá algunos cambios de ruta dentro de los files que hacen reference a algunos files renombrados / movidos.

Mi problema es que para mostrar la diferencia de un file que ha sido renombrado y luego modificado, git diff también muestra un montón de windows fusionadas para files que han sido renombrados, pero no modificados. Esto puede ser muy molesto ¿Cómo get git diff para omitir los files renombrados pero no modificados? Voy a ver todos los files enumerados como renombrados / movidos cuando escribo el estado de git de una manera mucho más limpia, así que no quiero las windows emergentes para files idénticos con git diff.

Estoy teniendo el mismo problema y se me ocurrió un alias que hizo el truco (estoy usando git 2.8.3)

 [alias] difftoolr = "!git difftool \"$@\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" 

Cómo utilizar:

 difftoolr commit1..commit2 -M 

(ver en la parte inferior para más ejemplos)

Cómo funciona:

Imagine que tiene tres files que han sido renombrados. Uno de ellos tiene su contenido realmente cambiado (por lo que desea examinarlo utilizando su difftool), pero los otros dos son idénticos, excepto por la ruta o el nombre (y desea ignorarlos).

 (different) path/file.old -> newPath/file.new (identical) path/fileB.old -> newPath/fileB.new (identical) path/fileC.old -> newPath/fileC.new 

Lo que hace el alias es generar especificaciones de ruta que excluyen explícitamente fileB y fileC , es decir, aquellos files que, a pesar del cambio de nombre, tienen el contenido inalterado.
En otras palabras, estamos generando estas funciones de file:

 -- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new 

Observe la parte (quizás la más complicada): la antigua ruta del file y la nueva ruta del file deben estar explícitamente excluidas.

Para hacerlo, git diff un git diff con las siguientes directivas:

  • -M100% : sigue los -M100% nombre. Lo que significa que git está asumiendo que se realizó un cambio de nombre, y tomará esta información en count para hacer comparaciones por pares. El umbral es 100%, lo que indica a git que considere renombrar los files que tienen exactamente el mismo contenido, pero no los que fueron alterados.
  • --diff-filter=R : enumera solo los files que git considera renombrados, omite los otros.
  • --names-only : solo --names-only los nombres de los files, ninguna otra información
  • -R : Reverse. En una parte del guión intercambiamos el order de comparación (tipo de cambio de los lados izquierdo y derecho), por lo que también se mostrarán los nombres de los files antiguos. Por ejemplo, la directiva -R enumera el file newPath/fileB.new como path/fileB.old .
  • ...sed... : y finalmente agregamos la directiva de exclusión :(exclude) al comienzo de todos los nombres de file.

Para tratar con otros casos, creé tres alias diferentes (no muy elegante, me gustaría algo más flexible) por lo que se puede utilizar para especificar los diferentes types de comparación.

 git difftoolr0 -M git difftoolr1 HEAD~1..HEAD -M git difftoolr2 HEAD --cached -M 

En todos los casos, los "lados de las comparaciones" (commits, –cached o lo que sea) se deben especificar como los primeros parameters. Por ejemplo, git difftoolr2 -M HEAD --cached no funcionará (porque -M es lo primero).

 [alias] # takes no parameter: sample usage: git difftoolr0 -M difftoolr0 = "!git difftool \"$@\" -- . $((git diff -M100% --diff-filter=R --name-only & git diff -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" # takes 1 parameter in first position: sample usage: git difftoolr1 HEAD~1..HEAD -M difftoolr1 = "!git difftool \"$@\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" # takes 2 parameters in first positions: sample usage: git difftoolr2 HEAD --cached -M difftoolr2 = "!git difftool \"$@\" -- . $((git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only & git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" 

Finalmente, BeyondCompare también puede satisfacer sus necesidades (y la mía).
Permite fácilmente cambiar el diferencial lado a lado en una diferencia "no estructurada".

Este último quita las carpetas y deja solo los nombres. Si el nombre del file es el mismo (pero las routes pueden diferir) se consideran dos versiones del mismo file (por ejemplo, path/file.png y newPath/file.png ). En este caso, si el contenido no ha cambiado, se pueden omitir fácilmente usando un button en la barra superior.

En caso de que ocurra un "nombramiento" de conflictos (varios files en el mismo lado de la comparación tienen el mismo nombre, en diferentes routes), elegiría solo uno de ellos para la comparación e ignoraría los demás.