Reorganizar el Trabajo Realizado
RebaseEn Git hay dos formas de integrar cambios de una rama en otra: merge y rebase.
En esta seccion veremos que es la reorganizacion (rebase), como hacerla, por que es una herramienta bastante util, y en que casos no conviene usarla.
Volvamos al ejemplo de la seccion de fusion. Tenemos dos ramas divergentes: master y experiment.
La forma mas sencilla de integrar las ramas es merge, que realiza una fusion entre las dos ultimas instantaneas de cada rama (C3 y C4) y su ancestro comun (C2), generando una nueva confirmacion con dos padres.
Sin embargo, tambien puedes tomar los cambios introducidos en C4 y reaplicarlos encima de C3.
En Git, esto se llama reorganizar (rebase).
Con el comando git rebase, puedes tomar todos los cambios confirmados en una rama y reaplicarlos sobre otra:
git checkout experiment
git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
Lo que hace es ir al ancestro comun de las dos ramas (experiment y master),
calcular las diferencias introducidas por cada confirmacion de experiment,
guardar esas diferencias en archivos temporales,
actualizar la rama experiment al mismo punto que master,
y finalmente aplicar ordenadamente cada diferencia.
Ahora solo queda volver a master y hacer un fast-forward:
git checkout master
git merge experimentEl resultado final es identico al de la fusion, pero el historial queda mas limpio: parece que todo el trabajo se hizo en serie, aunque en realidad se hizo en paralelo.
El rebase reproduce confirmaciones en el mismo orden en que fueron creadas, mientras que la fusion toma los puntos finales y los une.
El rebase puede aplicarse sobre una rama que no sea su base directa.
Supongamos un historial como este: una rama server creada a partir de master para agregar funcionalidades del lado del servidor, y una rama client creada a partir de server para cambios del lado del cliente.
Quieres integrar los cambios de client en master para publicarlos, pero dejar los cambios de server aparte hasta que esten mejor probados.
Puedes usar git rebase --onto para tomar los commits de client que no estan en server y reaplicarlos sobre master:
git rebase --onto master server clientEsto significa: “toma la rama
client, averigua los cambios desde que divergio deserver, y aplicalos sobremaster”.
Ahora puedes hacer fast-forward de master:
git checkout master
git merge client
Cuando los cambios de server esten listos, puedes reorganizarlos sobre master sin tener que hacer checkout antes:
git rebase master serverEsto significa: “toma la rama
server, averigua los cambios desde que divergio demaster, y aplicalos sobremaster”.
Y finalmente integrar y limpiar:
git checkout master
git merge server
git branch -d client
git branch -d server
tar -xzf 10-rebase-onto.tar.gzcd 10-rebase-onto/code .) y lee el README.mdEl rebase tiene un coste: nunca reorganices confirmaciones que ya hayas enviado a un repositorio publico.
Si reorganizas commits que otros ya tienen como base de su trabajo, les estaras causando problemas serios. Cuando reorganizas, Git descarta las confirmaciones originales y crea otras nuevas que son similares pero distintas. Si alguien tenia trabajo basado en esas confirmaciones originales, tendra que refusionar su trabajo, y el historial se volvera un caos.
Clonas desde un servidor central y haces algo de trabajo local.
Alguien mas hace trabajo, incluyendo una fusion, y lo envia al servidor. Haces git fetch y obtienes esas confirmaciones.
Luego fusionas ese trabajo en tu rama local.
Pero entonces esa persona decide reorganizar su trabajo en vez de fusionar, y hace git push --force sobreescribiendo el historial en el servidor.
Cuando vuelves a hacer git fetch, obtienes las nuevas confirmaciones reorganizadas.
Ahora ambos estan en un lio. Si haces git pull, crearas una fusion confirmada que incluye ambas lineas del historial, y el repositorio quedara con confirmaciones duplicadas (el trabajo original y su version reorganizada), lo cual genera confusion.
Si te encuentras en esta situacion, Git tiene algunos recursos que pueden ayudarte.
Ademas del checksum SHA-1 del commit, Git calcula un checksum basado en el parche que introduce cada confirmacion — el llamado patch-id.
Si te traes el trabajo sobreescrito y lo reorganizas sobre las nuevas confirmaciones de tu companero con git rebase teamone/master,
Git puede identificar automaticamente que parte correspondia a tu trabajo y aplicarla de vuelta.
En vez de una nueva fusion confusa, el resultado sera un historial mas limpio.
Esto solo funciona si los parches de tu companero son muy similares a los originales.
Tambien puedes simplificar el proceso usando git pull --rebase en vez del git pull tradicional,
o hacerlo manualmente con git fetch seguido de git rebase teamone/master.
Si sueles usar git pull y quieres que --rebase este activado por defecto:
git config --global pull.rebase true
Si solo reorganizas confirmaciones que nunca han estado disponibles publicamente, estaras bien. Si reorganizas confirmaciones sobre las que otros han basado su trabajo, prepárate para problemas.
Ahora que has visto ambas herramientas, te preguntaras cual es mejor. Para responder, vale la pena pensar en que representa el historial.
Para algunos, el historial de un repositorio es un registro de todo lo que ha pasado: un documento historico valioso por si mismo que no deberia alterarse. Cambiar el historial de confirmaciones es casi como falsificar la historia.
Para otros, el historial es la historia de como se hizo el proyecto: algo que se edita y refina antes de publicar, igual que un borrador de un libro o un manual de instrucciones.
No hay una respuesta unica correcta. Git es una herramienta poderosa y cada equipo decide segun su contexto.
Reorganiza libremente en ramas locales o en ramas puntuales que solo tu estes trabajando.
Evita el rebase en ramas de largo recorrido compartidas (master, develop, etc.) o en cualquier rama sobre la que alguien mas haya basado su trabajo.
Entrar al kahoot y esperar el codigo de la sala, o presionar la opcion “Aprende” para responder de forma individual.
3.6