A principios de este año hice una reorganización interactiva por primera vez y me impresionó lo que se puede hacer con ella. También me pareció un poco complejo al principio. Con suerte, esta guía ayudará a eliminar cierta incertidumbre al respecto.
Además, debido a que es tan poderoso y esencialmente puede reescribir la historia, una pequeña advertencia antes de comenzar: hay muchas escuelas de pensamiento sobre Git y si reorganizar es una buena idea o no. Esta publicación no se sumergirá en esas discusiones y tiene la intención pura de explicar los conceptos básicos del uso de rebase interactivo.
git commit --amend
en lugar de git commit
.En este ejemplo, trabajaremos en una situación en la que hemos estado trabajando en una rama de función y tenemos un par de compromisos que nos gustaría cambiar o eliminar. Así es como se ve nuestro registro de git:
Desde el registro de git anterior, aquí están las dos confirmaciones que queremos cambiar: 4a4d705
- En esta confirmación cometimos accidentalmente un conflicto de combinación 6c01350
- En esta confirmación eliminamos el conflicto de combinación
Lo que nos gustaría hacer es retroceder en el tiempo hasta 4a4d705
, eliminar el conflicto de combinación en la confirmación y luego eliminar 6c01350
, ya que el conflicto de combinación está resuelto y ya no necesitamos esta confirmación. Esta será una mejora en nuestro historial de confirmaciones por dos razones:
Esta situación es una buena candidata para el cambio de base interactivo. Scott Chacon, en su libro Pro Git , describe el cambio de base interactivo de la siguiente manera: “A veces, lo que se solucionó... no se puede modificar a la confirmación no del todo perfecta que corrige, porque esa confirmación está profundamente enterrada en una serie de parches. Eso es exactamente para lo que sirve el rebase interactivo: utilícelo después de mucho [trabajo comprometido], reorganizando y editando confirmaciones, y agrupando múltiples confirmaciones en una sola”.
Para iniciar una reorganización interactiva, debemos decirle a Git qué confirmaciones queremos modificar. Hacemos esto haciendo referencia a la confirmación inmediatamente anterior a la primera confirmación que queremos modificar. O, en pocas palabras, hacemos referencia a "la última confirmación [que] queremos conservar tal como está", según Scott Chacon.
Veamos nuestro ejemplo para tener una mejor comprensión. Hay dos formas de hacer referencia a esta confirmación: Por SHA-1 : la última confirmación que queremos conservar tal cual tiene un SHA-1 de 528f82e
para que podamos pasar esto a nuestro comando de rebase interactivo. Por índice : la última confirmación que queremos conservar tal como está tiene una posición de índice de 3 (Git usa indexación basada en cero) para que podamos pasar HEAD~3
a nuestro comando de rebase interactivo.
Nota: si solo tiene algunas confirmaciones en las que realizar una reorganización interactiva, usar el índice probablemente sea más fácil para la mayoría de las personas. Sin embargo, si tiene muchas confirmaciones, usar SHA-1 probablemente sea más fácil para que no tenga que contar todo el registro de git.
Basándonos en nuestro ejemplo, ejecutaremos:
$ git rebase -i 528f82e
O
$ git rebase -i HEAD~3
Lo que abre esta ventana en Vim:
Observe que las confirmaciones están en el orden opuesto al registro de git. En el registro de git, la confirmación más reciente está en la parte superior. En esta vista, la confirmación más reciente está en la parte inferior. También observe que los comentarios a continuación brindan una lista útil de los comandos válidos que podemos usar en cada confirmación.
Si no conoce Vim, simplemente haga clic en cada pick
de palabra que desee editar y luego presione la tecla <i>
(para el modo de inserción). Una vez que haya terminado de escribir, presione la tecla <esc>
para salir del modo de inserción.
En nuestro ejemplo, hemos cambiado el comando para edit
para la confirmación que queremos modificar y hemos cambiado el comando para drop
para la confirmación que queremos eliminar. Luego ejecutamos :wq
para guardar y salimos de la ventana de Vim.
De vuelta en la terminal vemos este mensaje:
Esto tiene sentido que nos detengamos en 4a4d705
. Esta es la confirmación más antigua de la serie de confirmaciones que queremos modificar. Comenzaremos con este compromiso y avanzaremos a través de cada compromiso hasta el más reciente.
Como recordatorio, 4a4d705
fue la confirmación con el conflicto de combinación que cometimos accidentalmente. Cuando abrimos nuestro editor, vemos el conflicto de fusión allí:
Así que solucionamos el conflicto de combinación en el archivo, pero ¿qué hacemos ahora? En caso de duda, git status
:
¡Enfriar! Esto es realmente útil. Vemos que actualmente estamos editando 4a4d705
, y vemos que se actuará sobre los siguientes dos compromisos después de este.
El resto del mensaje nos explica un flujo de trabajo familiar. Git nos dice si queremos modificar la confirmación, ejecutamos git commit --amend
. Básicamente, esto actuará como nuestro típico git commit
que usamos en un flujo de trabajo normal. En la parte inferior de este mensaje, vemos que nuestro archivo se modificó reflejando los cambios que acabamos de hacer para eliminar el conflicto de combinación. Necesitamos organizar el archivo antes de comprometernos. Esto no es diferente de un flujo de trabajo normal.
Todo lo que hacemos es git add tempChanger.js
para preparar el archivo editado y luego git commit --amend
para confirmar el archivo preparado. Esto ahora abrirá una ventana de Vim nuevamente con el mensaje de confirmación:
Podemos editar el mensaje de confirmación o dejarlo como está. Elijamos mantener el mismo mensaje de confirmación y escribiremos :wq
para guardar y salir de la ventana.
Ahora hemos editado nuestro antiguo compromiso. ¿Y ahora que? Ejecute el git status
:
No tenemos nada más que cambiar en el compromiso, así que ¡continuemos!
git rebase --continue
y vemos el siguiente mensaje:
Vaya, ¿hemos terminado? Pero, ¿qué pasa con esos otros dos compromisos? Bueno, el siguiente compromiso en el que se actuó fue 6c01350
. Esta confirmación la marcamos para eliminar ( drop
) cuando comenzamos la reorganización interactiva. Git lo eliminó automáticamente y pasó a la siguiente confirmación, 41aa9d2
. Este nunca fue modificado en el rebase interactivo inicial. Su comando predeterminado era pick
lo que significa que se usará la confirmación. Git aplicó ese compromiso y, dado que ese fue el último compromiso, se completó la reorganización interactiva.
Tenga en cuenta que, si tuviéramos más confirmaciones para editar, simplemente pasaríamos a la siguiente confirmación y comenzaríamos el proceso de modificación tal como lo hicimos anteriormente. El ciclo continúa hasta que no quedan confirmaciones.
Vale la pena señalar que si en algún momento de nuestro rebase interactivo arruinamos las cosas y no sabemos cómo solucionarlas, siempre podemos abortar. En cualquier momento, podemos ejecutar git rebase --abort
en la terminal y el rebase interactivo se cancelará sin guardar los cambios. Entonces tendríamos que volver a iniciar la reorganización interactiva.
Nuestro registro de git ahora se ve así:
Notará que algunas cosas han cambiado desde antes de que comenzáramos la reorganización interactiva:
6c01350
con el mensaje de confirmación "Eliminar conflicto de combinación". Esta es la confirmación que eliminamos en nuestra reorganización interactiva.4a4d705
, tiene un SHA-1 diferente, 2b7443d
.41aa9d2
, también tiene un nuevo SHA-1, 2b95e92
. Esta confirmación no se modificó sino que simplemente se aplicó a la confirmación anterior 2b7443d
. Para las dos confirmaciones más recientes en nuestro registro de git, debido a que tienen nuevos SHA-1, Git las ve como confirmaciones completamente nuevas. Esto es cierto incluso para nuestra última confirmación, 2b95e92
, donde ni el mensaje de confirmación ni los archivos cambiaron en absoluto. Esto trae a colación un punto importante con el cambio de base interactivo: si modifica una confirmación, esa confirmación y todas las confirmaciones sucesivas tendrán nuevos SHA-1.
Esto no afectará nada si las confirmaciones que ha modificado no se han enviado a una rama remota. Sin embargo, si de hecho completó una reorganización interactiva en las confirmaciones que ya se enviaron a una rama remota y luego volvió a enviar su rama, vería:
Técnicamente, podría solucionar esto usando git push --force
, pero eso es muy peligroso. Si la sucursal remota tiene confirmaciones de otras personas pero su sucursal local aún no tiene esas confirmaciones, eliminará efectivamente sus confirmaciones.
Otra solución es usar git push --force-with-lease
que solo modificará tus confirmaciones pero no las confirmaciones que pertenezcan a otros, aunque esto también puede ser problemático. Por ejemplo, si otro desarrollador ya tiene esas confirmaciones a las que se les dieron nuevos SHA-1 en su sucursal local, cuando extraen la sucursal remota, tendrán conflictos de combinación con cada una de estas confirmaciones.
Cuándo usar --force-with-lease
está más allá del alcance de esta publicación de blog, pero sería mejor consultar a otros miembros de su equipo antes de hacerlo. Puedes leer más sobre git push --force-with-lease
aquí .
La conclusión clave de esta sección es que es mucho más fácil y seguro usar el cambio de base interactivo en confirmaciones que aún no se han enviado a una rama remota.
Escrito por Blake DeBoer. Publicado originalmente en Dev.to
¿Desarrollador senior, líder o principal en la ciudad de Nueva York? ¡ Stride está contratando ! ¿Quieres subir de nivel a tu equipo técnico? ¡Mira cómo lo hacemos ! www.stridenyc.com