Diferencias entre git fetch, pull y rebase

logo de git

No sé cómo estás acostumbrado a trabajar en git. En mi caso, cuando quiero traerme los cambios del servidor a mis ramas locales, uso siempre git pull. Sin embargo, sé que existen git fetch y git rebase, que nunca uso.

Veamos qué hace cada una y cuándo podemos usarlas.

git fetch

Esta es la más básica. Se asegura que de nuestra copia local de git tiene los cambios que se hayan hecho en el servidor. NO modifica nuestro código ni nuestras ramas ni nada. Sólo se trae a nuestra caché local de git los cambios que se hayan hecho en el servidor.

Es una forma de asegurarnos de que nuestro git local es consciente de todos los cambios que se hayan hecho en el servidor, pero sin que haga cambios en nuestras copias de trabajo locales.

Esto es útil luego para comandos como git status. Si tenemos los cambios del servidor en nuestra copia local, este comando será capaz de decirnos si estamos actualizados, si nos faltan actualizaciones, etc.

git pull

git pull sí hace cosas con nuestra copia local. Primero ejecuta un git fetch para ver todos los cambios que se han hecho en el servidor y actualizar nuestra caché local. Pero luego hace un git merge para mezclar los cambios remotos con los nuestros locales. Es decir, actualiza nuestra copia de trabajo y modifica nuestro código para que tenga los cambios que se hayan hecho en el servidor remoto.

Si hay conflictos nos los indicará y los tendremos que resolver, pero nuestro copia de código quedará actualizada con lo último que haya en el servidor más los cambios que hubiéramos hecho nosotros en local.

git rebase

Este comando es similar a git pull en el sentido de que trae los cambios a tu rama de trabajo. Pero tiene dos diferencias notables

La primera es que no hace un git fetch primero de forma automática. Si quieres traer cambios del servidor remoto para mezclarlos con tu rama de trabajo, debes ejecutar primero el comando git fetch manualmente.

Y la segunda diferencia, que se la más importante, es que mezcla los cambios en tu rama pero como si los hubieras hecho en la misma rama. Vamos a ver esto con detalle para ver exactamente qué queremos decir.

Imagina que han hecho cambios en remoto y nosotros en local. Ejecutamos git pull. En local tendremos ambos cambios, pero la historia de git quedaría de esta forma

Es decir, dos ramas separadas, una con los cambios en local, la otra con los cambios en remoto y un merge de ambas, que quedaría en nuestra rama master

Si en vez de un git pull hubiéramos hecho un git rebase, tendríamos igualmente todos los cambios en nuestro lado, pero la historia quedaría así

Es decir, trae los cambios de remoto y los mete en nuestra rama como si los hubiéramos hecho nosotros mismos. La historia, desde luego, queda más limpia, pero perdemos parte de ella. No los commits, que siguen ahí, sino de dónde vienen a nivel de ramas. Qué usuario los ha hecho y en qué fecha sí se mantiene.

Peligros de git rebase

Puesto que git rebase mueve cambios de una rama a otra, tiene cierto peligro. Si tu forma de trabajo es similar a git flow, es decir, los desarrolladores hacen ramas de git para cada nueva funcionalidad, luego la mezclan en una rama común de nombre develop y cuando se llega a una versión para entregar del SW se hace una copia en una rama de versiones congeladas de nombre master, puede ser peligroso el uso de git rebase. No porque sea malo, sino porque o bien los desarrolladores saben muy bien qué están haciendo, o pueden llevarse por error commits de una rama a otras que no deben.

Por ejemplo, en git-flow las ramas feature son las de desarrollo de funcionalidades. Quizás es buena idea que una vez terminada una feature, se haga un git rebase para llevarse la feature a la rama develop. Esto nos deja una historia más limpia en develop, como si hubiésemos desarrollado directamente en ella.

Pero si por equivocación un desarrollador lo hace al revés, es decir, trae los cambios de develop a su rama feature, en develop dejarán de estar todos los cambios posteriores al momento en el que se hizo la rama para la feature. El resto de desarrolladores dejarán de verlos si el desarrollador hace un push.

git pull deja la historia más sucia, con muchas ramas entremezcladas, pero no es tan susceptible de equívocos. Las dos ramas originales permanecen inalteradas siempre y únicamente aparece un único commit para la mezcla de ambas ramas. Este último commit, en caso de error, siempre se puede echar atrás fácilmente.

Esta entrada ha sido publicada en git y etiquetada como , , , , , . Guarda el enlace permanente.

Deja una respuesta

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.