el comando git rebase
tiene una reputación de ser mágico git voodoo del que los principiantes deben mantenerse alejados, pero en realidad puede hacer la vida mucho más fácil para un equipo de desarrollo cuando se usa con cuidado. En este artículo, compararemos git rebase
con el comando git merge
relacionado e identificaremos todas las oportunidades potenciales para incorporar el reajuste en el flujo de trabajo típico de Git.,
Descripción Conceptual
Lo primero que hay que entender acerca degit rebase
es que resuelve el mismo problema quegit merge
. Ambos comandos están diseñados para integrar los cambios de una rama en otra rama – simplemente lo hacen de maneras muy diferentes.
considere lo que sucede cuando comienza a trabajar en una nueva característica en una rama dedicada, luego otro miembro del equipo actualiza la ramamaster
con nuevas confirmaciones. Esto resulta en un historial bifurcado, que debería ser familiar para cualquiera que haya utilizado Git como herramienta de colaboración.,
Ahora, digamos que el nuevo cometa en el master
son relevantes para la función que se esté trabajando. Para incorporar las nuevas confirmaciones en su rama feature
, tiene dos opciones: fusionar o rebasear.,
la opción Merge
la opción más fácil es combinar la rama master
en la rama feature usando algo como lo siguiente:
git checkout feature git merge master
o, puede condensar esto en una sola línea:
git merge feature master
esto crea un nuevo «merge commit» en la rama feature
que une los historiales de ambas ramas, dándole una estructura de ramas que se ve así:
fusionar es bueno porque es una operación no destructiva. Las ramas existentes no se cambian de ninguna manera., Esto evita todas las trampas potenciales de la reorganización (discutidas más adelante).
por otro lado, esto también significa que la rama feature
tendrá un commit de fusión extraño cada vez que necesite incorporar cambios de upstream. Si master
está muy activo, esto puede contaminar bastante el historial de su rama de características. Si bien es posible mitigar este problema con las opciones avanzadas git log
, puede dificultar que otros desarrolladores entiendan el historial del proyecto.,
la opción Rebase
como alternativa a la fusión, puede rebase la rama feature
En master
usando los siguientes comandos:
git checkout feature git rebase master
esto mueve toda la rama feature
Branch para comenzar en la punta de la rama master
, incorporando efectivamente todas las nuevas confirmaciones en master
. Pero, en lugar de usar una confirmación merge, rebasing reescribe el historial del proyecto creando nuevas confirmaciones para cada confirmación en la rama original.,
El principal beneficio de rebasing es que obtienes un historial de proyectos mucho más limpio. Primero, elimina las confirmaciones de fusión innecesarias requeridas por git merge
. En segundo lugar, como puede ver en el diagrama anterior, el cambio de base también resulta en un historial del proyecto perfectamente lineal: puede seguir la punta de feature
hasta el comienzo del proyecto sin bifurcaciones. Esto hace que sea más fácil navegar sus proyectos con los comandos como git log
, git bisect
y gitk
.,
pero, hay dos compensaciones para este prístino historial de commits: seguridad y trazabilidad. Si no sigues la regla de oro del cambio de Base, reescribir el historial del proyecto puede ser potencialmente catastrófico para tu flujo de trabajo de colaboración. Y, lo que es menos importante, el rebasing pierde el contexto proporcionado por una confirmación de fusión: no se puede ver cuándo se incorporaron los cambios de upstream a la característica.
Rebasing interactivo
El rebasing interactivo te da la oportunidad de modificar las confirmaciones a medida que se mueven a la nueva rama., Esto es incluso más poderoso que un rebase automatizado, ya que ofrece un control completo sobre el historial de Confirmaciones de la rama. Normalmente, esto se usa para limpiar un historial desordenado antes de fusionar una rama de característica en master
.,
Para comenzar una sesión de rebase interactiva, pase la opción i
al comando git rebase
:
git checkout feature git rebase -i master
Esto abrirá un editor de texto con todas las confirmaciones que están a punto de ser movidas:
pick 33d5b7a Message for commit #1 pick 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3
esta lista define exactamente cómo se verá la rama después de que se realice la rebase. Cambiando el comando pick
y / o reordenando las entradas, puede hacer que el historial de la rama se vea como lo que quiera., Por ejemplo, si el 2º cometer corrige un pequeño problema en la 1ª cometer, puede condensar en un único commit con el fixup
comandos:
pick 33d5b7a Message for commit #1 fixup 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3
Cuando usted guarde y cierre el archivo, Git realizar el reajuste de acuerdo a sus instrucciones, resultando en un proyecto de historia que tiene el siguiente aspecto:
Eliminar insignificante compromete como este, hace su función que es la historia mucho más fácil de entender. Esto es algo que git merge
simplemente no puede hacer.,
La regla de oro del Rebasing
Una vez que entiendes lo que es el rebasing, lo más importante que debes aprender es cuándo no hacerlo. La regla de oro de git rebase
es nunca usarlo en ramas públicas.
Por ejemplo, pensar en qué pasaría si rebasada master
en el feature
rama:
El reajuste mueve todos los commits en el master
en la punta de feature
. El problema es que esto solo sucedió en su repositorio., Todos los demás desarrolladores siguen trabajando con el master
original. Dado que el cambio de base resulta en nuevas confirmaciones, Git pensará que el historial de la rama master
ha divergido del de todos los demás.
la única forma de sincronizar las dos ramas master
es fusionarlas de nuevo, lo que resulta en una confirmación de fusión adicional y dos conjuntos de confirmaciones que contienen los mismos cambios (las originales y las de tu rama rebasada). Huelga decir que esta es una situación muy confusa.,
entonces, antes de ejecutargit rebase
, siempre pregúntese: «¿alguien más está mirando esta rama?»Si la respuesta es sí, quite las manos del teclado y comience a pensar en una forma no destructiva de hacer sus cambios (por ejemplo, el comando git revert
). De lo contrario, puedes reescribir la historia todo lo que quieras.
Force-Pushing
si intentas empujar la rama rebasada master
de nuevo a un repositorio remoto, Git evitará que lo hagas porque entra en conflicto con la rama remota master
., Sin embargo, puede forzar el push pasando la bandera --force
, como así:
# Be very careful with this command! git push --force
esto sobrescribe la rama remota master
para que coincida con la rebasada de su repositorio y hace que las cosas sean muy confusas para el resto de su equipo. Por lo tanto, tenga mucho cuidado de usar este comando solo cuando sepa exactamente lo que está haciendo.
una de las pocas veces que debería forzar el envío es cuando ha realizado una limpieza local después de haber enviado una rama de Característica privada a un repositorio remoto (por ejemplo, para fines de copia de seguridad)., Esto es como decir: «Oops, realmente no quería impulsar esa versión original de la rama de características. Tome el actual en su lugar.»Una vez más, es importante que nadie esté trabajando fuera de las confirmaciones de la versión original de la rama de características.
Tutorial del flujo de trabajo
el rebase se puede incorporar a tu flujo de trabajo de Git tanto o tan poco como tu equipo se sienta cómodo. En esta sección, echaremos un vistazo a los beneficios que el rebase puede ofrecer en las diversas etapas del desarrollo de una característica.,
el primer paso en cualquier flujo de trabajo que aproveche git rebase
es crear una rama dedicada para cada característica. Esto le da la estructura de rama necesaria para utilizar de forma segura el rebase:
limpieza Local
Una de las mejores maneras de incorporar el rebase en su flujo de trabajo es limpiar las características locales en curso. Al realizar periódicamente un rebase interactivo, puede asegurarse de que cada confirmación en su función esté enfocada y sea significativa., Esto le permite escribir su código sin preocuparse por dividirlo en confirmaciones aisladas—puede arreglarlo después del hecho.
al llamar a git rebase
, tiene dos opciones para la nueva base: la rama principal de la característica (por ejemplo, master
), o una confirmación anterior en su característica. Vimos un ejemplo de la primera opción en la sección de rebase interactivo. La última opción es buena cuando solo necesitas arreglar las últimas confirmaciones. Por ejemplo, el siguiente comando comienza un rebase interactivo de solo las últimas 3 confirmaciones.,
git checkout feature git rebase -i HEAD~3
al especificar HEAD~3
como la nueva base, en realidad no estás moviendo la rama, solo estás reescribiendo interactivamente las 3 confirmaciones que le siguen. Tenga en cuenta que esto no incorporará los cambios en la rama feature
.
Si desea reescribir toda la función utilizando este método, el comando git merge-base
puede ser útil para encontrar la base original de la rama feature
., Lo siguiente devuelve el ID de confirmación de la base original, que luego puede pasar a git rebase
:
git merge-base feature master
Este uso del rebase interactivo es una gran manera de introducir git rebase
en su flujo de trabajo, ya que solo afecta a las ramas locales. Lo único que otros desarrolladores verán es su producto terminado, que debe ser un historial de rama de características limpio y fácil de seguir.
pero de nuevo, esto solo funciona para ramas de características privadas., Si estás colaborando con otros desarrolladores a través de la misma rama de funciones, esa rama es pública y no se te permite reescribir su historial.
no hay git merge
alternativa para limpiar confirmaciones locales con un rebase interactivo.
incorporar cambios ascendentes en una característica
en la sección Descripción Conceptual, vimos cómo una rama de característica puede incorporar cambios ascendentes desdemaster
usandogit merge
ogit rebase
., La fusión es una opción segura que conserva todo el historial de su repositorio, mientras que el cambio de Base crea un historial lineal moviendo su rama de entidad a la punta de master
.
este uso de git rebase
es similar a una limpieza local (y se puede realizar simultáneamente), pero en el proceso incorpora los commits de master
.
tenga en cuenta que es perfectamente legal rebase en una rama remota en lugar de master
., Esto puede suceder cuando colaboras en la misma función con otro desarrollador y necesitas incorporar sus cambios en tu repositorio.,
por ejemplo, si usted y otro desarrollador llamado John agregaron confirmaciones a la rama feature
, su repositorio podría tener el siguiente aspecto después de obtener la rama remota feature
desde el repositorio de John:
puede resolver esta bifurcación exactamente de la misma manera que integra cambios desde master
: combine su local feature
con john/feature
, o rebase su local feature
en la punta de john/feature
.,
tenga en cuenta que este rebase no viola la regla de oro del rebase porque solo sus Confirmaciones locales feature
se están moviendo, todo lo anterior está intacto. Esto es como decir, » agrega mis cambios a lo que Juan ya ha hecho.»En la mayoría de las circunstancias, esto es más intuitivo que la sincronización con la rama remota a través de una confirmación de fusión.
de forma predeterminada, el comando git pull
realiza una fusión, pero puede forzarlo a integrar la rama remota con una rebase pasándole la opción --rebase
.,
revisar una función con una solicitud de extracción
Si utiliza solicitudes de extracción como parte de su proceso de revisión de código, debe evitar usar git rebase
después de crear la solicitud de extracción. Tan pronto como hagas la solicitud de extracción, otros desarrolladores estarán mirando tus commits, lo que significa que es una rama pública. Reescribir su historial hará imposible que Git y tus compañeros de equipo rastreen cualquier confirmación de seguimiento agregada a la función.
Cualquier cambio de otros desarrolladores deben ser incorporados con la etiqueta git merge
en lugar de git rebase
.,
por esta razón, generalmente es una buena idea limpiar su código con un rebase interactivo antes de enviar su solicitud de extracción.
integrar una función aprobada
después de que su equipo haya aprobado una función, tiene la opción de cambiar la base de la función en la punta de la rama master
antes de usar git merge
para integrar la función en la base de código principal.,
Esta es una situación similar a la incorporación de cambios upstream en una rama feature, pero ya que no se le permite volver a escribir confirmaciones en la rama master
, tiene que usar eventualmente git merge
para integrar la característica. Sin embargo, al realizar un rebase antes de la fusión, está seguro de que la fusión será reenviada rápidamente, lo que resulta en un historial perfectamente lineal. Esto también te da la oportunidad de aplastar cualquier confirmación de seguimiento agregada durante una solicitud de extracción.,
Si no se siente completamente cómodo con git rebase
, siempre puede realizar el rebase en una rama temporal. De esa manera, si accidentalmente estropeas el historial de tu característica, puedes revisar la rama original e intentarlo de nuevo. Por ejemplo:
git checkout feature git checkout -b temporary-branch git rebase -i master # git checkout master git merge temporary-branch
Summary
y eso es todo lo que realmente necesita saber para comenzar a reorganizar sus ramas., Si prefiere un historial limpio y lineal libre de Confirmaciones de fusión innecesarias, debe buscar git rebase
en lugar de git merge
al integrar cambios desde otra rama.
por otro lado, si desea preservar el historial completo de su proyecto y evitar el riesgo de reescribir confirmaciones públicas, puede seguir con git merge
. Cualquier opción es perfectamente válida, pero al menos ahora tiene la opción de aprovechar los beneficios de git rebase
.
Deja una respuesta