Crear un parche en GIT es una excelente manera de compartir cambios que aún no está listo para enviar al público rama de un proyecto.
Para comprender mejor cómo crearemos un parche, primero hablemos un poco sobre cómo cambian las tiendas GIT.
Si es nuevo en GIT, instálelo y comience con este artículo de introducción a GIT.
La primera vez que se envía un archivo a un proyecto en GIT, se almacena una copia. Para todas las confirmaciones posteriores, GIT esencialmente almacena instrucciones que le indican cómo transformar la versión anterior del proyecto en la nueva versión confirmada.
En GIT, estas instrucciones se denominan "diffs" . Siempre que pague una rama, GIT básicamente comenzará en el estado original del proyecto y aplicará todas estas diferencias en orden para llegar al estado deseado.
Sabiendo ahora cómo GIT almacena las confirmaciones, es fácil ver que un archivo de parche será simplemente una concatenación de las diferencias para cada una de las confirmaciones que abarcará el parche.
Para nuestro ejemplo, supongamos la siguiente situación:Tenemos un proyecto simple con 2 ramas:maestra y experimental.
$ git log --oneline --all * b36f227 (experimental) third commit -- added file3 * f39ebe8 second commit -- added file2 * 04a26e5 (HEAD, master) first commit -- committed file1
Master se encuentra actualmente en la primera confirmación, mientras que experimental tiene 2 confirmaciones por delante. En cada confirmación, agregué un archivo llamado file1, file2 y file3 respectivamente. Aquí está el estado actual de cada sucursal:
En el maestro, solo tenemos el archivo 1:
$ git status On branch master nothing to commit, working directory clean $ ls file1
Mientras estamos en fase experimental, tenemos los 3 archivos:
$ git status On branch experimental nothing to commit, working directory clean $ ls file1 file2 file3
En este tutorial, explicaremos cómo crear un parche de los cambios en la rama experimental y aplicarlos al maestro.
Creación del parche GIT
Usaremos el comando git diff para crear la salida diff, luego la redirigiremos a un archivo. La forma del comando diff que usaremos es la siguiente:
git diff from-commit to-commit > output-file
donde:
- from-commit:el punto en el que queremos que comience el parche. (En nuestro caso, el punto en el que experimental diverge de maestro)
- para confirmar:el parche abarcará los cambios hasta este punto incluido. (En nuestro caso, la confirmación más reciente de experimental)
- archivo de salida:el parche se escribirá aquí
Nota:si se omiten from-commit o to-commit, se supondrá que son HEAD
Especificamos las dos confirmaciones por su hash único. Por lo general, solo tiene que especificar lo suficiente del hash de confirmación para garantizar su unicidad (probablemente 4 caracteres lo harán).
$ git diff 04a2 b36f > patch.diff $ ls patch.diff file1 file2 file3
Como puede ver en el resultado anterior, se ha creado el archivo de parche.
En este caso especial, en el que queremos crear un parche de toda la rama, podemos dejar que GIT haga parte del trabajo por nosotros. Podemos dejar que GIT determine el punto en el que nuestra rama experimental se separó de la rama maestra usando el comando git merge-base:
git diff $(git merge-base <public branch> <experimental branch>) > <output file>
git merge-base determinará la confirmación común más reciente entre 2 sucursales. Note también cómo esta vez hemos omitido . Se establecerá de forma predeterminada en HEAD y, dado que se desprotegió la rama experimental, HEAD será la confirmación más reciente de la rama experimental.
$ git diff $(git merge-base master experimental) > anotherPatch.diff $ ls anotherPatch.diff patch.diff file1 file2 file3
Una vez más, se ha creado el archivo de parche. Estos archivos de parches son idénticos.
Aplicación del parche GIT
Una vez que se ha creado el archivo de parche, aplicarlo es fácil. Asegúrese de que la rama que ha verificado es a la que desea aplicar el parche (maestro en nuestro caso). Luego puede aplicar el parche usando el comando git apply:git apply
$ git status On branch master ... (rest of output omitted) ... $ ls anotherPatch.diff patch.diff file1 $ git apply patch.diff $ ls anotherPatch.diff patch.diff file1 file2 file3
Los cambios de la rama experimental ahora se han replicado en el maestro.
Advertencia:aunque la aplicación de un parche de esta manera replicará exactamente el contenido, no se replicará ningún historial de confirmaciones. Esto significa que incluso si el parche que crea abarca varias confirmaciones, aparecerá como un único conjunto de cambios cuando se aplique. Perderá tanto el conocimiento de cómo se dividieron las confirmaciones como los mensajes de cada confirmación. Comparemos el historial de confirmación de ambas ramas:
En el experimento, tuvimos 3 confirmaciones, cada una con un mensaje de confirmación significativo.
$ git branch * experimental master $ git log --oneline b36f227 third commit -- added file3 f39ebe8 second commit -- added file2 04a26e5 first commit -- committed file1
Sin embargo, nuestro parche simplemente aplicó los cambios reales a la rama maestra.
$ git branch experimental * master $ git log --oneline 04a26e5 first commit -- committed file1
La aplicación del parche no confirmó los cambios, ni trajo nada del historial de confirmación asociado con estos cambios. Tenga cuidado con esto cuando use parches en GIT.