![¿A qué archivos se aplica ` patch -p1` el parche en este ejemplo?](https://rvso.com/image/109227/%C2%BFA%20qu%C3%A9%20archivos%20se%20aplica%20%60%20patch%20-p1%60%20el%20parche%20en%20este%20ejemplo%3F.png)
Para revertir los cambios a un archivo en una confirmación, desdehttps://stackoverflow.com/a/2620822/156458
#!/bin/bash
function output_help {
echo "usage: git-revert-single-file <sha1> <file>"
}
sha1=$1
file=$2
if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi
¿A qué archivos se patch -p1
aplica el archivo de parche (es decir, la salida de git diff $sha1..$sha1^ -- $file
)?
¿Se aplica a todos los archivos del directorio de trabajo?
Pero es posible que el directorio de trabajo no sea el mismo que el de confirmación $sha1
. Entonces, ¿tiene sentido aplicar la diferencia entre $sha1^
y $sha1
al directorio de trabajo, que podría ser el mismo o no $sha1
?
Gracias.
Respuesta1
git diff $sha1..$sha1^
produce un parche que revierte la $sha1
confirmación (enumera las diferencias entre esa confirmación y su padre). Si $file
se especifica, limita ese parche a los cambios realizados $file
en la confirmación dada.
Luego, ese parche se envía a patch -p1
, lo que eliminará los nombres de directorio falsos utilizados por git
( a/
y b/
) e intentará aplicar el parche a los archivos enumerados en el parche (es decir, $file
si se nombró y se modificó en la confirmación dada, o todos los archivos cambiaron en la confirmación dada, incluidos los archivos en subdirectorios). Si los archivos presentes en el directorio actual y sus subdirectorios son sustancialmente diferentes (o, por extensión, faltan), patch
no se podrá aplicar el parche.
Esto es posible gracias al hecho de que los parches en formato unificado, producidos por git diff
(y diff -u
), incluyen los nombres de los archivos que se están parcheando y el contexto del parche. Aquí hay un ejemplo (no de git
, pero muestra la idea):
diff -ur cli-common-0.9+nmu1.orig/policy-remove cli-common-0.9+nmu1/policy-remove
--- cli-common-0.9+nmu1.orig/policy-remove 2015-02-25 21:34:08.000000000 +0100
+++ cli-common-0.9+nmu1/policy-remove 2017-04-08 20:47:09.029065259 +0200
@@ -11,4 +11,4 @@
#echo "Removing GAC policy file ($POLICY) from available GACs"
/usr/share/cli-common/gac-package-remove $POLICY > /dev/null
-rm /usr/share/cli-common/packages.d/$POLICY.installcligac
+rm -f /usr/share/cli-common/packages.d/$POLICY.installcligac
Este parche dice que está modificando el archivo denominado cli-common-0.9+nmu1.orig/policy-remove
para producir el archivo denominado cli-common-0.9+nmu1/policy-remove
. El cambio en sí comienza en la línea 11 y cubre 4 líneas, incluido el contexto (ese es el @@ -11,4
); en el objetivo, las líneas modificadas están en la misma posición ( +11,4 @@
). Hay tres líneas de contexto encima del cambio, luego el cambio en sí, eliminando una línea que comienza con rm
y agregando una línea que comienza con rm -f
. Cuando patch
se aplica esto, buscará el archivo con el nombre apropiado (después de eliminar los componentes de la ruta si se le indica con una -p
opción) y comparará el contexto en el archivo con el parche; solo si el contexto coincide (dentro de unas pocas líneas, dependiendo de las opciones de fuzz) se aplicará el cambio.
El objetivo de este script es intentar revertir los cambios realizados en un solo archivo en la confirmación dada (de ahí su nombre). Si eso es posible o no depende de los cambios que se hayan realizado en el archivo desde esa confirmación; pero suele ser bastante útil en la práctica. (Para revertir una confirmación completa, usaría git revert
en su lugar).