git rebase
Definición
Rebase significa mover o combinar una serie de commits a un nuevo commit base. En otras palabras, cambia la base de la rama actual de un commit a otro, haciendo que parezca que la rama se ha creado a partir de otro commit. Esto se hace ejecutando el comando git rebase. Ten en cuenta que, aunque la rama parezca la misma, está compuesta por commits totalmente nuevos.

Uso del comando git rebase
En primer lugar, necesitamos este comando para mantener un historial lineal del proyecto. Por ejemplo, la rama master avanza después de que empiezas a trabajar en una rama de funcionalidad. Necesitas las actualizaciones recientes de la rama master en tu rama de funcionalidad, pero el historial de la rama master debe permanecer limpio. Necesitamos un historial claro al ejecutar operaciones de Git para rastrear regresiones. Encuentra más información sobre el uso de git rebase a continuación:
La inadmisibilidad de rebasear el historial público
Nunca rebasees commits después de publicarlos en el historial público. Al igual que en el caso de modificar y restablecer, esto causará problemas para la colaboración en equipo. Si lo haces, el commit antiguo será reemplazado por uno nuevo y parecerá que parte de tu proyecto ha desaparecido.
La diferencia entre Git rebase estándar y Git rebase interactivo.
Hay dos modos del comando git rebase: estándar e interactivo. En el modo estándar, git rebase aplicará automáticamente los commits de la rama de trabajo actual a la cabeza de la rama pasada como argumento. La rama actual se rebaseará sobre <code><base></code>. Esto puede ser de distintos tipos de referencias de commit, como una etiqueta, un ID, un nombre de rama, etc.
comando git rebase
git rebase <base>En el modo interactivo, git rebase se ejecuta con la bandera -i, que significa “interactivo”. La ventaja de rebasear en modo interactivo es cambiar los commits individuales durante el proceso, sin tener que mover todos los commits a la nueva base. Gracias a este modo, puedes limpiar el historial eliminando y modificando la secuencia existente de commits.
Ejecutar el siguiente comando abrirá un editor:
git rebase -i
git rebase --interactive <base>En este editor, introduce los comandos que se indican a continuación para cada commit que deba rebasearse. Git comenzará a reproducir los commits y a aplicar los comandos de rebase, después de determinar los comandos para cada commit.
ejemplo de git rebase
pick 11a1456 some old commit
pick a23db19 Adds new feature
# Rebase 31d332c..a23db19 onto 31d332c (9 commands)
#
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commitComandos de rebase interactivo
Durante un rebase interactivo, puedes usar los siguientes comandos para cada commit de la lista de tareas:
drop: descarta el commit del bloque final de commits combinados durante la reproducción.pick: conserva el commit tal cual, sin editar el mensaje ni el contenido, dejándolo como un commit individual en el historial de la rama.exec: permite ejecutar un script de shell de línea de comandos sobre cada commit marcado durante la reproducción.
Recapitulación de Git
Una de las ventajas del rebase interactivo es que permite a los desarrolladores no preocuparse por el desorden del historial del proyecto, ya que luego pueden volver y limpiarlo. Por eso, muchos desarrolladores usan esta herramienta para hacer más limpio el historial de la rama de funcionalidad antes de fusionarla con la rama master. Limpiar una rama significa eliminar commits sin sentido o ya obsoletos. Como resultado, los desarrolladores tienen un historial bien planificado y pueden entender fácilmente qué commits se han realizado.
Opciones de configuración
Existen algunas opciones de rebase que se establecen con la ayuda del comando git config. Estas opciones alteran el comportamiento y la salida de git rebase.
- rebase.stat: por defecto, un booleano falso, que alterna la visualización del contenido visual de diffstat que muestra los cambios desde el último rebase.
- rebase.autoSquash: un valor booleano que alterna el comportamiento de
--autosquash. - rebase.missingCommitsCheck: puede establecerse en varios valores que cambian el comportamiento del rebase en relación con los commits faltantes. | warn | Se imprime una salida de advertencia en modo interactivo y advierte sobre los commits eliminados. | |---|---| | error | El rebase se detiene y se imprimen mensajes de advertencia sobre los commits eliminados. | | ignore | La opción predeterminada, que ignora cualquier advertencia sobre commits faltantes. |
- rebase.instructionFormat: una cadena en formato de git log usada para dar formato a la visualización del rebase interactivo.
Aplicación avanzada de rebase
Se puede pasar git rebase al argumento de línea de comandos --onto, en cuyo caso el comando se expande a lo siguiente:
git rebase --onto
git rebase --onto <newbase> <oldbase> <branch>El comando --onto proporciona una aplicación avanzada de rebase, ya que permite pasar refs específicas como commits base del rebase.
Veamos su comportamiento con un ejemplo:
git rebase --onto example
o---o---o---o---o master
\
o---o---o---o---o featureX
\
o---o---o featureYAunque featureY originalmente se basaba en featureX, es independiente de los cambios de featureX y puede rebasearse directamente sobre master. Este comando reproduce los commits de featureY sobre master, separando efectivamente featureY de featureX.
comando git rebase --onto
git rebase --onto master featureX featureYFeatureX es <code><oldbase></code>, master es <code><newbase></code>, y featureY es la rama que se está rebaseando. Este es el resultado:
uso de git rebase
o---o---o featureY
/
o---o---o---o---o master
\
o---o---o---o---o featureXLos peligros de rebasear
El primer peligro de usar el comando git rebase es que puede causar más conflictos de fusión durante un proceso de rebase, especialmente en los casos en que tienes una rama de larga duración que se ha desviado de master. Tarde o temprano, puedes decidir rebasear contra master, que puede contener algunos commits nuevos con los que los cambios de tu rama pueden entrar en conflicto. La solución a la situación descrita anteriormente es rebasear la rama contra master con más frecuencia y hacer commits más frecuentes. Para continuar o abortar el rebase mientras resuelves conflictos, puedes usar los argumentos --continue y --abort con git rebase. Otro riesgo más serio es que algunos commits puedan perderse al reescribir el historial interactivo. Ejecutar rebase en modo interactivo con algunos subcomandos como squash o drop elimina commits del registro inmediato de la rama. Puede parecer que los commits se eliminan permanentemente. La solución es git reflog, que permite restaurar estos commits y deshacer todo el rebase.
Recuperación tras un rebase en upstream
En caso de que otro usuario haya rebaseado y hecho force-push a la rama a la que estás haciendo commits, un git pull sobrescribirá entonces cualquier commit que hayas basado en esa rama anterior con la punta enviada mediante force-push. Git rebase te permite usar el reflog de la rama remota. Allí puedes encontrar una ref anterior a su rebase. Luego puedes rebasear tu rama contra esa ref remota con la opción --onto.
Práctica
What are the correct statements about the `git rebase` command as described in the W3Docs Git Tutorial?