No temas al rebase

      No hay comentarios en No temas al rebase

No temas al rebase


El comando rebase de GIT es una fuente de miedos y confusión para los usuarios de GIT, especialmente para aquellos que viene de un sistema de control de versiones más centralizado. Es normal. Rebase es una bestia mágica y extraña que acaba de llegar y cambia la historia queramos o no.
Rebase es parecido a los punteros, es algo confuso de lo que todo el mundo habla, pero no tienes ni idea de porque alguien querría usarlo y de repente todo ‘encaja’ y el concepto nos parece obvio e increíblemente simple.
Estamos aquí para conseguir ese ‘encaje’ de forma que puedas difundir las maravillas de lo que es git rebase.

¿Pero qué es un Rebase?

Git Rebase es una sencilla herramienta que podemos usar para tomar varios commits hechos en un lugar y ‘finjir’ que se hicieron en otro todos juntos

Vale pero, ¿eso que significa?

Miremos este ejemplo. Tenemos dos ramas en este repositorio: master y feature/foo. feature/foo es una rama de master y se hicieron varios commits en feature/foo. master también se ha movido, porque el mundo no se para cuando dejamos de mirar.

Estado actual


Queremos integrar los cambios de master en feature/foo pero no queremos un commit del merge cada vez que vamos a realizar esta integración.
Rebase es la herramienta que da la posibilidad de integrar cambios que se llevaron a cabo en la rama de origen sin hacer un merge, y consecuentemente, sin tener el commit del merge.

Después del rebase


Los commits D y F se han vuelto a realizar en master, que actualmente apunta al commit G. Habrás notado que esos commits en realidad se llaman D’ y F’ y el SHA-1 del commit es diferente. ¿Por qué?

Los commits de GIT son inmutables

Un commit tiene algunas propiedades que son relevantes en este caso: un commit padre, una marca de tiempo (timestamp) y una instantánea del repositorio en el momento del commit (los commits no son sólo conjuntos de cambios). Estos valores son los que usa GIT para generar el SHA-1 que identifica al commit.
Dado que los commits son inmutables y un SHA-1 debería identificar unívocamente un commit, GIT tiene que crear nuevos commits que contiene la misma instantánea del repositorio que los commits originales, pero cada uno con un commit padre y timestamp diferentes.
Esto nos lleva a que los nuevos commits parecen idénticos a los originales, pero tienen diferente SHA-1.

Encontrando los commits

¿Cómo sabe GIT qué commits mover cuando ejecutamos git rebase master desde feature/foo?
Observemos primero el diagrama de Venn con los commits de cada rama.

Aquí vemos que cada rama tiene los commits A, B y C. master tiene los commits E y G que no tiene feature/foo. Además, feature/foo tiene los commits F y D que master no tiene.
GIT realizará una resta, {commits en feature/foo} - {commits en master}, para encontrar los commits correctos. El resultado son los commits D y F.

¿Podemos comprobarlo?

¡Sí! Una forma sencilla es usar git log para ver exactamente los commits obtenidos de esta resta.
git log master...feature/foo debería mostrarnos los commits bc1f36b y 640e713.

Se toma la rama actual si se omite después de los tres puntos (…)


Por ahora todo parece correcto. Vamos a obtener una visión más amplia para asegurarnos.

Estos SHA-1 nos suenan…


76f5fd1 y 22033eb no están porque salimos de master en 7559a0b


Si ahora hacemos un rebase en master, deberíamos ver los commits 76f5fd1 y 22033eb justo antes de los commits que se hicieron en feature/foo.

GIT está volviendo a aplicar los commits que esperábamos



¿Nos suena esto?

¡Esto ya lo habíamos visto!


Ahora tenemos una bonita historia lineal. Ahora deberíamos ser capaces de ver como un merge fast-forward sucede en este punto.

La estrategia de rebase tiene el añadido de saber que si tu flujo de integración continua para la rama de la feature, también pasará la rama principal tras el merge. Sin una estrategia de merge lineal, no lo podemos garantizar

Usando Force

Si feature/foo ya había sido pushed y se intenta realizar otro push después de este rebase, GIT declinará hacerlo. ¿Por qué?
GIT hará todo lo posible para evitar una sobreescritura accidental de la historia, lo cual es algo bueno.
Echemos un vistazo al aspecto que GIT pienas que debe tener feature/foo en el repositorio remote,

Ahora veamos lo que le estamos indicando a GIT que tiene que hacer.

Desde el punto de vista de GIT, los commits D y F están a punto de perderse. GIT te dará un bonito mensaje junto con el texto Las actualizaciones se han rechazado porque el final de tu rama actual está detrás
Podríamos pensar «Veo claramente en la imagen que feature/foo está por delante de lo que estaba antes». Es una buena observación, pero GIT sólo ve que feature/foo en el repositorio remoto contiene bc1f36b y 640e713 y nuestra versión local de feature/foo no contiene esos commits. Así que, para no perder esos commits, GIT declinará un git push, solicitando un git push --force.
Si vas a quedarte con una sola cosa de este artículo, recuerda que rebase tan sólo encuentra commits que se hicieron en una rama y crea nuevos commits con el mismo contenido, pero con un nuevo padre o commit base.

Nota: puedes encontrar el artículo original en https://hackernoon.com/dont-fear-the-rebase-bca683888dae

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *