Las sucursales multiplican la funcionalidad básica ofrecida por los compromisos al permitir a los usuarios compartir su historial. Crear una nueva rama es similar a solicitar un nuevo entorno de desarrollo, completo con un directorio de trabajo aislado, área de preparación e historial de proyectos.
Esto le brinda la misma tranquilidad que al enviar una copia "segura" de su proyecto, pero ahora tiene la capacidad adicional de trabajar en varias versiones al mismo tiempo. Las ramas permiten un flujo de trabajo no lineal-La capacidad de desarrollar características no relacionadas en paralelo. Como veremos más adelante, un flujo de trabajo no lineal es un importante precursor de la naturaleza distribuida del modelo de colaboración de Git..
A diferencia de SVN o CVS, la implementación de la rama de Git es increíblemente eficiente. SVN permite a las sucursales copiar todo el proyecto en una nueva carpeta, como harías sin ningún software de control de revisiones. Esto hace que las fusiones sean torpes, propensas a errores y lentas. En contraste, las ramas de Git son simplemente un puntero a un commit. Dado que trabajan en el nivel de confirmación en lugar de hacerlo directamente en el nivel de archivo, las sucursales de Git facilitan mucho la combinación de historias divergentes. Esto tiene un impacto dramático en los flujos de trabajo de ramificación..
Git separa la funcionalidad de rama en unos pocos comandos diferentes. los rama de git
El comando se utiliza para listar, crear o eliminar ramas..
En primer lugar, deberá poder ver sus sucursales existentes:
rama de git
Esto generará todas sus sucursales actuales, junto con un asterisco junto al que está "desprotegido" actualmente (más sobre esto más adelante):
* dominar algunas características de corrección rápida de errores
los dominar
branch es la rama por defecto de Git, que se crea con la primera confirmación en cualquier repositorio. Muchos desarrolladores utilizan esta rama como la historia "principal" del proyecto, una rama permanente que contiene cada cambio importante que atraviesa.
Puede crear una nueva rama pasando el nombre de la rama a la misma rama de git
mando:
rama de git
Esto crea un puntero a la corriente. CABEZA
, pero hace no cambiar a la nueva rama (necesitarás git checkout
para eso). Inmediatamente después de solicitar una nueva sucursal, su repositorio tendrá un aspecto similar al siguiente.
Su rama actual (dominar
) y la nueva sucursal (alguna característica
) ambos hacen referencia al mismo compromiso, pero cualquier nuevo compromiso que registre será exclusivo de la rama actual. Nuevamente, esto le permite trabajar en características no relacionadas en paralelo, mientras mantiene un historial sensible. Por ejemplo, si tu rama actual era alguna característica
, su historial se vería como el siguiente después de cometer una instantánea.
alguna característica
rama El nuevo CABEZA
(indicado por el compromiso resaltado) existe solo en el alguna característica
rama. No aparecerá en la salida de registro de dominar
, ni sus cambios aparecerán en el directorio de trabajo una vez que haya realizado el check out dominar
.
Puedes ver la nueva rama en la base de datos interna abriendo el archivo .git / refs / heads /
. El archivo contiene el ID de la confirmación a la que se hace referencia, y es la única definición de una rama Git. Esta es la razón por la cual las sucursales son tan livianas y fáciles de manejar.
Por último, puede eliminar sucursales a través de -re
bandera:
rama git -d
Pero, la dedicación de Git a no perder nunca su trabajo le impide eliminar sucursales con compromisos no combinados. Para forzar la eliminación, use la -re
bandera en su lugar:
rama git -D
Los cambios no combinados se perderán, por lo que ten mucho cuidado con este comando.
Por supuesto, crear ramas es inútil sin la capacidad de cambiar entre ellas. Git llama a esto "revisar" una rama:
git checkout
Después de verificar la rama especificada, su directorio de trabajo se actualiza para que coincida con el compromiso de la rama especificada. además, el CABEZA
se actualiza para que apunte a la nueva rama, y todas las confirmaciones nuevas se almacenarán en la nueva rama. Puede pensar en revisar una rama como cambiar a una nueva carpeta de proyecto, excepto que será mucho más fácil volver a introducir los cambios en el proyecto.
Con esto en mente, generalmente es una buena idea tener un limpiar Directorio de trabajo antes de retirar una sucursal. Existe un directorio limpio cuando no hay cambios no confirmados. Si este no es el caso, git checkout
tiene el potencial de sobrescribir tus modificaciones.
Al igual que con la confirmación de una revisión "segura", puede experimentar en una nueva rama sin temor a destruir la funcionalidad existente. Pero ahora tiene un historial dedicado con el que trabajar, por lo que puede registrar el progreso de un experimento utilizando exactamente el mismo git añadir
y git commit
comandos de antes en el libro.
Esta funcionalidad se volverá aún más poderosa una vez que aprendamos a combinar historias divergentes en la rama "principal" (por ejemplo,., dominar
). Llegaremos a eso en un momento, pero primero, hay un caso de uso importante de git checkout
Eso debe ser considerado ...
Git también te permite usar git checkout
con las etiquetas y las ID de confirmación, pero al hacerlo te pone en una estado HEAD separado. Esto significa que ya no estás en una sucursal, estás viendo directamente un commit.
Puede mirar alrededor y agregar nuevas confirmaciones como de costumbre, pero como no hay ninguna rama que apunte a las adiciones, perderá todo su trabajo tan pronto como vuelva a una rama real. Afortunadamente, creando una nueva sucursal en un separado. CABEZA
Estado es bastante fácil:
git checkout -b
Este es un atajo para rama de git
seguido por git checkout
. Después de lo cual, tendrá una nueva y brillante referencia de rama a la que anteriormente se había separado. CABEZA
. Este es un procedimiento muy útil para forzar experimentos a partir de revisiones antiguas..
La fusión es el proceso de tirar los compromisos de una rama a otra. Hay muchas maneras de combinar sucursales, pero el objetivo es siempre compartir información entre las sucursales. Esto hace que la fusión sea una de las características más importantes de Git. Las dos metodologías de fusión más comunes son:
Ambos usan el mismo comando., git merge
, pero el método se determina automáticamente según la estructura de su historial. En cada caso, La sucursal en la que desea fusionarse debe estar desprotegida., y la rama de destino se mantendrá sin cambios. Las siguientes dos secciones presentan dos posibles escenarios de combinación para los siguientes comandos:
git checkout master git fusionar alguna característica
Una vez más, esto combina la alguna característica
ramificarse en el dominar
Rama, dejando el anterior intacto. Normalmente, ejecutará estos comandos una vez que haya completado una función y desee integrarla en el proyecto estable.
El primer escenario se ve así:
Creamos una rama para desarrollar una nueva característica, agregamos dos confirmaciones y ahora está listo para integrarse en la base del código principal. En lugar de reescribir los dos errores que faltan dominar
, Git puede "adelantar" el dominar
puntero de la rama para que coincida con la ubicación de alguna característica
.
Después de la fusión, la dominar
La rama contiene todo el historial deseado, y la rama de la característica se puede eliminar (a menos que desee seguir desarrollándola). Este es el tipo más simple de fusión.
Por supuesto, podríamos haber hecho los dos compromisos directamente en el dominar
rama; sin embargo, el uso de una rama de funciones dedicadas nos dio un entorno seguro para experimentar con un nuevo código. Si no resultara del todo correcto, podríamos haber eliminado la rama (en lugar de restablecer / revertir). O, si agregamos un montón de confirmaciones intermedias que contienen código roto, podríamos limpiarlo antes de fusionarlo en dominar
(vea Rebasar abajo). A medida que los proyectos se vuelven más complicados y adquieren más colaboradores, este tipo de desarrollo ramificado hace de Git una herramienta organizativa fantástica..
Pero, no todas las situaciones son lo suficientemente simples para un compromiso de avance rápido. Recuerde, la principal ventaja de las sucursales es la capacidad de explorar muchas líneas independientes de desarrollo simultáneamente. Como resultado, a menudo se encontrará con un escenario similar al siguiente:
Esto comenzó como una combinación de avance rápido, pero agregamos un compromiso a la dominar
rama mientras todavía estábamos desarrollando alguna característica
. Por ejemplo, podríamos haber dejado de trabajar en la función para corregir un error sensible al tiempo. Por supuesto, la corrección de errores se debe agregar al repositorio principal tan pronto como sea posible, por lo que terminamos en el escenario que se muestra arriba.
Fusionando la rama de la característica en dominar
en este contexto resulta en una fusión de "3 vías". Esto se logra usando exactamente los mismos comandos que la combinación de avance rápido de la sección anterior.
Git no puede adelantar el dominar
puntero a alguna característica
sin retroceso. En su lugar, genera un nuevo fusionar cometer que representa la instantánea combinada de ambas ramas. Tenga en cuenta que este nuevo compromiso tiene dos los padres se comprometen, dándole acceso a ambas historias (de hecho, ejecutando registro de git
después de la combinación de 3 vías muestra confirmaciones de ambas ramas).
El nombre de este algoritmo de combinación se origina en el método interno utilizado para crear la confirmación de fusión. Git mira a Tres Se compromete a generar el estado final de la fusión..
Si intenta combinar dos ramas que realizan cambios diferentes en la misma parte del código, Git no sabrá qué versión usar. Esto se llama un fusionar conflicto. Obviamente, esto nunca puede suceder durante una fusión de avance rápido. Cuando Git encuentra un conflicto de combinación, verá el siguiente mensaje:
Fusión automática index.html CONFLICT (contenido): Fusionar conflicto enLa fusión automática falló; Arreglar conflictos y luego cometer el resultado..
En lugar de agregar automáticamente la confirmación de fusión, Git se detiene y le pregunta qué hacer. Corriendo estado de git
En esta situación se devolverá algo como lo siguiente:
# En la rama maestra # Rutas sin combinar: # # ambas modificadas:
Cada archivo con un conflicto se almacena en la sección "Rutas sin combinar". Git anota estos archivos para mostrarle el contenido de ambas versiones:
<<<<<<< HEAD This content is from the current branch. ======= This is a conflicting change from another branch. >>>>>>> alguna característica
La parte antes de la =======
es de la dominar
rama, y el resto es de la rama que estás tratando de integrar.
Para resolver el conflicto, elimina la <<<<<<
, =======
, y >>>>>>>
Notación, y cambia el código a lo que quieras conservar. Luego, dile a Git que has terminado de resolver el conflicto con el git añadir
mando:
git añadir
Está bien; todo lo que tiene que hacer es colocar el archivo en conflicto para marcarlo como resuelto. Finalmente, complete la combinación de 3 vías generando la confirmación de fusión:
git commit
El mensaje de registro se complementa con un aviso de combinación, junto con una lista de "conflictos", que puede ser particularmente útil cuando se trata de averiguar dónde algo salió mal en un proyecto.
Y eso es todo lo que hay que fusionar en Git. Ahora que entendemos la mecánica detrás de las sucursales de Git, podemos analizar en profundidad cómo los usuarios veteranos de Git aprovechan las sucursales en su flujo de trabajo diario..
Los flujos de trabajo presentados en esta sección son el sello distintivo del control de revisión basado en Git. La naturaleza liviana y fácil de fusionar de la implementación de la sucursal de Git las convierte en una de las herramientas más productivas de su arsenal de desarrollo de software..
Todos los flujos de trabajo ramificados giran en torno a la rama de git
, git checkout
, y git merge
comandos presentados anteriormente en este capítulo.
A menudo es útil asignar un significado especial a diferentes sucursales para organizar un proyecto. Esta sección presenta los tipos más comunes de ramas, pero tenga en cuenta que estas distinciones son puramente superficiales: para Git, una rama es una rama..
Todas las ramas se pueden categorizar como cualquiera permanente ramas o ramas del tema. Los primeros contienen la historia principal de un proyecto (por ejemplo,., dominar
), mientras que estas últimas son sucursales temporales utilizadas para implementar un tema, luego descartado (por ejemplo,., alguna característica
).
Las sucursales permanentes son el elemento vital de cualquier repositorio. Contienen cada punto importante de un proyecto de software. La mayoría de los desarrolladores usan dominar
Exclusivamente para código estable. En estos flujos de trabajo, Nunca comprometerse directamente en dominar
-es solo una rama de integración para las características completas que se construyeron en ramas de temas dedicados.
Además, muchos usuarios agregan una segunda capa de abstracción en otra rama de integración (llamada convencionalmente desarrollar
, aunque cualquier nombre será suficiente). Esto libera el dominar
rama para De Verdad código estable (por ejemplo, confirmaciones públicas) y usos desarrollar
como una rama de integración interna para preparar un lanzamiento público. Por ejemplo, el siguiente diagrama muestra varias características que se integran en desarrollar
, entonces una única y definitiva fusión en dominar
, que simboliza un lanzamiento público.
dominar
Sucursal exclusiva para lanzamientos públicos. Las ramas temáticas generalmente se dividen en dos categorías: ramas características y sucursales de hotfix. Las ramas de entidades son ramas temporales que encapsulan una nueva característica o refactor, protegiendo el proyecto principal del código no probado. Por lo general, se derivan de otra rama de características o una rama de integración, pero no de la rama "superestable".
Las sucursales de hotfix son similares en naturaleza, pero provienen de la sucursal pública (por ejemplo,., dominar
). En lugar de desarrollar nuevas funciones, son para parchear rápidamente la línea principal de desarrollo. Normalmente, esto significa correcciones de errores y otras actualizaciones importantes que no pueden esperar hasta la próxima versión importante.
dominar
con una rama de hotfix Nuevamente, los significados asignados a cada una de estas ramas son puramente convencionales: Git no ve diferencia entre dominar
, desarrollar
, Características, y revisiones. Con eso en mente, no tenga miedo de adaptarlos a sus propios fines. La belleza de Git es su flexibilidad. Cuando comprende la mecánica detrás de las sucursales de Git, es fácil diseñar flujos de trabajo novedosos que se ajusten a su proyecto y personalidad..
Rebasar es el proceso de mover una rama a una nueva base. Las capacidades de redistribución de Git hacen que las sucursales sean aún más flexibles al permitir a los usuarios organizar manualmente sus sucursales. Como fusionarse, git rebase
requiere que la rama esté desprotegida y toma la nueva base como argumento:
git checkout alguna característica git rebase master
Esto mueve todo el alguna característica
ramificar en la punta de dominar
:
alguna característica
sobre la dominar
rama Después de la rebase, la rama característica es una extensión lineal de dominar
, que es una forma mucho más clara de integrar los cambios de una rama a otra. Compara esta historia lineal con una fusión de dominar
dentro alguna característica
, que da como resultado exactamente la misma base de código en la instantánea final:
dominar
dentro alguna característica
con una combinación de 3 vías Dado que la historia se ha desviado, Git tiene que usar un compromiso de combinación adicional para combinar las sucursales. Hacer esto muchas veces en el transcurso del desarrollo de una función de larga duración puede resultar en un historial muy desordenado.
Estas confirmaciones de fusión adicionales son superfluas; existen solo para extraer cambios de dominar
dentro alguna característica
. Por lo general, querrás que tu combinación se comprometa a media algo, como la finalización de una nueva característica. Esta es la razón por la que muchos desarrolladores optan por introducir cambios con git rebase
, Ya que resulta en una historia completamente lineal en la rama de la característica.
La redistribución interactiva va un paso más allá y le permite cambio Se compromete a medida que los mueves a la nueva base. Puede especificar un rebase interactivo con el -yo
bandera:
git rebase -i maestro
Esto rellena un editor de texto con un resumen de cada confirmación en la rama de la característica, junto con un comando que determina cómo Debe ser transferido a la nueva base. Por ejemplo, si tiene dos confirmaciones en una rama de función, puede especificar una reorganización interactiva como la siguiente:
pick 58dec2a Primer commit para nueva característica squash 6ac8a9f Segundo commit para nueva característica
El valor por defecto recoger
comando mueve la primera confirmación a la nueva base al igual que la normal git rebase
, pero luego el squash
el comando le dice a Git que combine la segunda confirmación con la anterior, por lo que usted termina con una confirmación que contiene todos sus cambios:
alguna característica
rama Git proporciona varios comandos de rebasado interactivos, cada uno de los cuales se resume en la sección de comentarios del listado de configuración. El punto es el rebasado interactivo que te permite completamente reescribe el historial de una rama a tus especificaciones exactas. Esto significa que puede agregar tantos compromisos intermedios a una rama de función como necesite, luego retroceder y corregirlos en una progresión significativa después del hecho.
Otros desarrolladores pensarán que usted es un brillante programador, y sabía exactamente cómo implementar toda la función de una sola vez. Este tipo de organización es muy importante para garantizar que los grandes proyectos tengan un historial navegable.
Rebasar es una herramienta poderosa, pero debes ser juicioso en tu reescritura de la historia. Ambos tipos de rebasing no lo hacen movimiento compromisos existentes crear otros nuevos (indicados por un asterisco en el diagrama de arriba). Si inspecciona las confirmaciones que se sometieron a una rebase, notará que tienen diferentes ID, aunque representan el mismo contenido. Esto significa rebasar destruye cometidos existentes en el proceso de "moverlos".
Como puede imaginar, esto tiene consecuencias dramáticas para los flujos de trabajo colaborativos. Destruir un compromiso público (por ejemplo, cualquier cosa en el dominar
rama) es como arrancar la base del trabajo de todos los demás. Git no tendrá idea de cómo combinar los cambios de todos, y tendrás muchas disculpas por hacer. Examinaremos más a fondo este escenario después de aprender cómo comunicarnos con repositorios remotos..
Por ahora, solo respeta la regla de oro de rebasar: nunca rebasar una rama que ha sido empujada a un repositorio público.
Esta lección representa un capítulo de Git sucintamente, un libro electrónico gratuito del equipo en Syncfusion.