git diff
La comparación con diff es una función mediante la cual se toman dos conjuntos de datos de entrada y se muestran los cambios entre estos. git diff
es un comando multiusos de Git que, cuando se ejecuta, lleva a cabo una función para establecer las diferencias en los orígenes de datos de Git. Dichos orígenes de datos pueden ser confirmaciones, ramas y archivos, entre otras posibilidades. En el presente documento, examinaremos las invocaciones habituales de git diff
y los patrones del flujo de trabajo de comparación. El comando git diff
suele utilizarse junto con git status
y git log
para analizar el estado actual de un repositorio de Git.
Leer diferencias: resultados
Formato de salida sin procesar
Los siguientes ejemplos se ejecutarán en un solo repositorio, que se crea con los comandos indicados a continuación:
$:> mkdir diff_test_repo
$:> cd diff_test_repo
$:> touch diff_test.txt
$:> echo "this is a git diff test example" > diff_test.txt
$:> git init .
Initialized empty Git repository in /Users/kev/code/test/.git/
$:> git add diff_test.txt
$:> git commit -am"add diff test file"
[main (root-commit) 6f77fc3] add diff test file
1 file changed, 1 insertion(+)
create mode 100644 diff_test.txt
Si ejecutamos git diff
llegados a este punto, no habrá ningún resultado. Este es el comportamiento previsto, ya que no hay ningún cambio en el repositorio que permita mostrar diferencias. Cuando se haya creado el repositorio y hayamos añadido el archivo diff_test.txt
, podremos cambiar el contenido del archivo para empezar a experimentar con el resultado de la diferencia.
Material relacionado
rama de git
VER LA SOLUCIÓN
Aprende a usar Git con Bitbucket Cloud
$:> echo "this is a diff example" > diff_test.txt
Si ejecutas este comando, cambiarás el contenido del archivo diff_test.txt
. Cuando se haya modificado, podremos ver una diferencia y analizar el resultado. Ahora, al ejecutar git diff
, se producirá el resultado siguiente:
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example
Pasemos ahora a examinar un desglose más detallado del resultado de la diferencia.
1. Introducción de la comparación
diff --git a/diff_test.txt b/diff_test.txt
En esta línea se muestran las fuentes de entrada de la comparación. Podemos observar que se ha utilizado a/diff_test.txt
y b/diff_test.txt
en la comparación.
2. Metadatos
index 6b0c6cf..b37e70a 100644
En esta línea se muestran unos cuantos metadatos internos de Git. Lo más probable es que no necesites esta información. Los números de este resultado se corresponden con los identificadores hash de la versión del objeto de Git.
3. Marcadores de los cambios
--- a/diff_test.txt
+++ b/diff_test.txt
Estas líneas conforman una leyenda que asigna símbolos a cada origen de entrada de la comparación. En este caso, los cambios de a/diff_test.txt
se marcan con un ---
y, los de b/diff_test.txt
, con el símbolo +++
.
4. Fragmentos de la diferencia
El producto restante de la diferencia es una lista de "fragmentos" de la diferencia. Una diferencia solo muestra las secciones del archivo con cambios. En el ejemplo en cuestión, solo hay un fragmento porque estamos trabajando con un caso sencillo. Los fragmentos poseen su propia semántica pormenorizada del resultado.
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example
La primera línea es el encabezado del fragmento. Cada fragmento comienza con un encabezado delimitado por símbolos @@
. El contenido de dicho encabezado es un resumen de los cambios efectuados en el archivo. En nuestro ejemplo simplificado pone "-1 +1", lo que significa que ha habido cambios en la primera línea. En una diferencia más realista, se podría ver un encabezado como el siguiente:
@@ -34,6 +34,8 @@
En este ejemplo de encabezado, lo que pone es que se han extraído 6 líneas a contar desde la línea número 34. Además, se han añadido 8 líneas a partir de la línea número 34.
El resto del contenido del fragmento muestra los cambios recientes. Todas las líneas cambiadas comienzan por un símbolo +
o -
, que sirve para indicar de qué versión de la entrada de la comparación proceden los cambios. Como ya hemos comentado antes, -
indica cambios en a/diff_test.txt
, mientras que "+" indica cambios en b/diff_test.txt
.
Resaltar cambios
1. git diff --color-words
El comando git diff
también tiene un modo especial para resaltar los cambios con un nivel de detalle muy superior: ‐‐color-words
. Este modo tokeniza las líneas añadidas y eliminadas mediante espacios en blanco y luego muestra las comparaciones.
$:> git diff --color-words
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
this is agit difftest example
Ahora, el resultado muestra solo las palabras coloreadas que han cambiado.
2. git diff-highlight
Si clonas el código fuente de git, verás un subdirectorio llamado "contrib", que contiene una serie de herramientas relacionadas con Git, así como otras interesantes cositas que todavía no se han promovido al núcleo de Git. Una de ellas es un script en Perl llamado "diff-highlight". Diff-highlight empareja líneas coincidentes del resultado de la diferenciación y resalta los fragmentos menores que una palabra que han cambiado.
$:> git diff | /your/local/path/to/git-core/contrib/diff-highlight/diff-highlight
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example
De este modo, se reduce la diferencia al mínimo cambio posible.
Diferenciación de archivos binarios
Aparte de las utilidades para archivos de textos que hemos mostrado hasta el momento, git diff
también se puede ejecutar con archivos binarios. Por desgracia, el resultado predeterminado no resulta demasiado útil.
$:> git diff
Binary files a/script.pdf and b/script.pdf differ
Git tiene una función que te permite especificar un comando de shell para transformar el contenido de tus archivos binarios en texto antes de ejecutar el comando diff, pero para ello hay que hacer unos pequeños ajustes. En primer lugar, tienes que especificar un filtro de textconv que exponga cómo convertir en texto un tipo concreto de archivo binario. Usaremos una sencilla utilidad llamada "pdftohtml" (disponible a través de Homebrew) para convertir unos PDF en HTML legible para humanos. Puedes configurar esto para un solo repositorio editando el archivo .git/config
o bien globalmente editando ~ /.gitconfig
.
[diff "pdfconv"]
textconv=pdftohtml -stdout
Acto seguido, lo único que tienes que hacer es asociar al menos un patrón de archivos a nuestro filtro pdfconv, para lo cual puedes crear un archivo .gitattributes
en la raíz del repositorio.
*.pdf diff=pdfconv
Una vez configurado, git diff
ejecutará primero el archivo binario mediante el script de conversor configurado y producirá la comparación del resultado del conversor. Esta misma técnica se puede aplicar para obtener diferencias útiles de todo tipo de archivos binarios como, por ejemplo, archivos .zip o .jar. Por ejemplo: si utilizas unzip -l
(o semejante) en vez de "pdf2html", te mostrará las rutas que se han añadido o eliminado entre imágenes de confirmaciones. Por otro lado, se puede utilizar "exiv2" para mostrar cambios en los metadatos como, por ejemplo, documentos de dimensiones de imágenes. Asimismo, existen herramientas de conversión para transformar archivos .odf, .doc y otros formatos de documento a texto sin formato. Si no hay otra opción, las cadenas normalmente funcionarán con archivos binarios para los que no existe ningún conversor formal.
Comparar archivos: archivo git diff
En el comando git diff
se puede utilizar una opción de ruta de archivo explícita. Cuando se utiliza una ruta de archivo en git diff
, la operación de comparación limitará su alcance al archivo especificado. Los siguientes ejemplos ilustran este uso.
git diff HEAD ./path/to/file
En este ejemplo, el alcance se restringe a ./path/to/file
y, al invocar el comando, este comparará los cambios concretos efectuados en el directorio de trabajo con respecto al índice, y mostrará los cambios que todavía no se han preparado. De forma predeterminada, git diff
ejecutará la comparación con respecto a HEAD
. Si se omite HEAD
en el ejemplo anterior, git diff ./path/to/file
surtirá el mismo efecto.
git diff --cached ./path/to/file
Al invocar git diff
con la opción --cached
, el comando comparará los cambios preparados con el repositorio local. La opción --cached
equivale a --staged
.
Comparar todos los cambios
Al invocar git diff
sin ninguna ruta de archivo, se compararán los cambios efectuados en todo el repositorio. Los ejemplos anteriores con archivos concretos se pueden invocar sin el argumento ./path/to/file
y generar los mismos resultados en todos los archivos del repositorio local.
Cambios desde la última confirmación
De forma predeterminada, git diff
te mostrará todos los cambios sin confirmar desde la última confirmación.
git diff
Comparar archivos entre dos confirmaciones distintas
En el comando git diff
se pueden utilizar referencias de Git a confirmaciones para mostrar las diferencias. Por ejemplo, algunas de estas referencias son HEAD
, etiquetas y nombres de ramas. En Git, todas las confirmaciones tienen su correspondiente ID y, para obtenerlo, puedes ejecutar GIT LOG
. También puedes utilizar este ID de confirmación en git diff
.
git log --pretty=oneline
957fbc92b123030c389bf8b4b874522bdf2db72c add feature
ce489262a1ee34340440e55a0b99ea6918e19e7a rename some classes
6b539f280d8b0ec4874671bae9c6bed80b788006 refactor some code for feature
646e7863348a427e1ed9163a9a96fa759112f102 add some copy to body
$:> git diff 957fbc92b123030c389bf8b4b874522bdf2db72c ce489262a1ee34340440e55a0b99ea6918e19e7a
Comparar ramas
Comparar dos ramas
Las ramas se comparan igual que el resto de las entradas de referencia en git diff
.
git diff branch1..other-feature-branch
Este ejemplo introduce el punto como operador. Los dos puntos de este ejemplo indican que la entrada de diferencia son los extremos de ambas ramas. Si se omiten estos puntos y se utiliza un espacio entre las ramas, el efecto que se produce es el mismo. Además, está el operador de tres puntos:
git diff branch1...other-feature-branch
El operador de tres puntos inicia la comparación cambiando el primer parámetro de entrada, branch1
, ya que convierte branch1
en una referencia de la confirmación antecesora común compartida entre las dos entradas de diferencia, el antecesor compartido de branch1
y other-feature-branch. El último parámetro de entrada permanece inmutable como extremo de other-feature-branch.
Comparar archivos de dos ramas
Para comparar un archivo concreto entre ramas, hay que utilizar en el comando la ruta del archivo como tercer argumento de git diff
.
git diff main new_branch ./diff_test.txt
Resumen
En esta página se han analizado el proceso de comparación de Git y el comando git diff
. Hemos explorado cómo leer los resultados de git diff
y los distintos datos que estos incluyen. Se han dado ejemplos de cómo alterar el resultado de git diff
con resaltado y colores. Hemos examinado las estrategias de comparación como, por ejemplo, cómo ver las diferencias entre los archivos de ramas distintas y confirmaciones concretas. Además del comando git diff
, también hemos utilizado git log
y git checkout
.
Compartir este artículo
Tema siguiente
Lecturas recomendadas
Consulta estos recursos para conocer los tipos de equipos de DevOps o para estar al tanto de las novedades sobre DevOps en Atlassian.