Cuando trabajo con git en un equipo que usa ramas de características, a menudo me resulta difícil entender la estructura de la rama en la historia.
Ejemplo:
Digamos que hubo una función de rama de características / hacer café , y la corrección de errores continuó en el maestro en paralelo a la rama de características.
La historia podría verse así:
* merge feature/make-coffee
|\
| * small bugfix
| |
* | fix bug #1234
| |
| * add milk and sugar
| |
* | improve comments
| |
* | fix bug #9434
| |
| * make coffe (without milk or sugar)
| |
* | improve comments
|/
*
Problema
A primera vista, me resulta difícil saber de qué lado está la rama de características. Por lo general, necesito buscar varios comentarios en ambos lados para tener una idea de cuál es cuál. Esto se vuelve más complicado si hay varias ramas de características en paralelo (particularmente si son para características estrechamente relacionadas), o si se fusionó en ambas direcciones entre la rama de características y el maestro.
Como contraste, en Subversion, esto es significativamente más fácil porque el nombre de la sucursal es parte del historial, por lo que puedo decir de inmediato que una confirmación se realizó originalmente en "feature / make-coffee".
Git podría hacer esto más fácil al incluir el nombre de la rama actual en los metadatos de confirmación al crear una confirmación (junto con el autor, la fecha, etc.). Sin embargo, git no hace esto.
¿Hay alguna razón fundamental por la que esto no se hace? ¿O es que nadie quería la función? Si es lo último, ¿hay otras formas de entender el propósito de las ramas históricas sin ver el nombre?
Respuestas:
Probablemente porque los nombres de las ramas solo tienen sentido dentro de un repositorio. Si estoy en el
make-coffee
equipo y envío todos mis cambios a través de un guardián de puerta, mimaster
rama podría ser arrastrada a lamake-coffee-gui
sucursal del guardián de puerta , que se fusionará con sumake-coffee-backend
sucursal, antes de volver a cambiar a unamake-coffee
sucursal que se fusiona con lamaster
sucursal central .Incluso dentro de un repositorio, los nombres de las sucursales pueden cambiar y cambian a medida que evoluciona su flujo de trabajo.
master
podría cambiar más tarde para ser llamadodevelopment
, por ejemplo.Como aludió CodeGnome, git tiene una sólida filosofía de diseño de no incluir algo en los datos si no es necesario. Se espera que los usuarios usen opciones
git log
ygit diff
generen los datos a su gusto después del hecho. Recomiendo probar algunos hasta que encuentre un formato que funcione mejor para usted.git log --first-parent
, por ejemplo, no mostrará las confirmaciones de una rama que se está fusionando.fuente
Seguimiento de la historia de la sucursal con
--no-ff
En Git, un commit tiene antepasados, pero una "rama" es realmente solo el jefe actual de alguna línea de desarrollo. En otras palabras, un commit es una instantánea del árbol de trabajo en algún momento y puede pertenecer a cualquier número de ramas a la vez. Esto es parte de lo que hace que la ramificación de Git sea tan liviana en comparación con otros DVCS.
Las confirmaciones de Git no llevan información de sucursal porque no son necesarias para el historial de Git. Sin embargo, las fusiones que no son de avance rápido ciertamente pueden llevar información adicional sobre qué rama se fusionó. Puede asegurarse de que su historial contenga esta información pasando siempre la
--no-ff
bandera a sus fusiones. git-merge (1) dice:Esto generalmente creará un mensaje de fusión similar a
Merge branch 'foo'
, por lo que normalmente puede encontrar información sobre "ramas ancestrales" con una línea similar a la siguiente:fuente
git log --merges
.La respuesta más simple es que los nombres de las ramas son efímeros. ¿Y si tuviera que, por ejemplo, cambiar el nombre de una rama (
git branch -m <oldname> <newname>
)? ¿Qué pasaría con todos los compromisos contra esa rama? ¿O qué pasa si dos personas tienen sucursales que tienen el mismo nombre en diferentes repositorios locales?Lo único que tiene significado en git es la suma de verificación del commit en sí. Esta es la unidad básica de seguimiento.
La información está ahí, simplemente no la está solicitando, y no está exactamente allí.
Git almacena la suma de comprobación de la cabeza de cada rama en
.git/refs/heads
. Por ejemplo:(sí, estoy golpeando mis sumas de comprobación de git, no es especial, pero son repositorios privados que estoy viendo en ese momento que no necesitan que se filtre accidentalmente).
Al mirar esto y rastrear cada commit que tiene esto como un padre, o el padre de los padres o el padre de los padres ... puede averiguar en qué ramas se encuentra un compromiso determinado. Es solo un gran gráfico para representar.
Almacenar donde específicamente el nombre de una rama (que puede cambiar como se mencionó anteriormente) es una confirmación en la confirmación en sí es una sobrecarga adicional en la confirmación que no lo ayuda. Almacene el padre (s) del commit y es bueno.
Puede ver las ramas ejecutando el comando git log con el indicador correspondiente.
Hay muchas formas diferentes de elegir lo que desea para eso: consulte la documentación de registro de git , la
-all
sección y las pocas opciones que siguen.Esa 'prueba', 'prueba1' y 'prueba2' son las ramas a las que se comprometieron.
Tenga en cuenta que la documentación de registro de git es enorme y es muy posible obtener casi cualquier cosa que desee.
fuente
¿Por qué los git commits no contienen el nombre de la rama en la que se crearon?
Solo una decisión de diseño. Si necesita esa información, puede agregar un enlace prepare-commit-msg o commit-msg para aplicarlo en un único repositorio.
Después del desastre de BitKeeper, Linus Torvalds desarrolló git para que coincida con el proceso de desarrollo del kernel de Linux. Allí, hasta que se acepte un parche, se revisa, edita, pule varias veces (todo a través del correo), se cierra la sesión (= editar una confirmación), se selecciona, deambula por las ramas del teniente, a menudo se puede rebajar, más ediciones, cereza -púas y así sucesivamente hasta que finalmente se fusionen río arriba por Linus.
En dicho flujo de trabajo, puede que no haya un origen específico de una confirmación, y a menudo se crea una confirmación en alguna rama de depuración temporal en algún repositorio aleatorio privado sin importancia con nombres de ramas divertidos, ya que se distribuye git.
Tal vez esa decisión de diseño solo ocurrió por coincidencia, pero coincide exactamente con el proceso de desarrollo del kernel de Linux.
fuente
Porque en Git los compromisos como "hacer café" se consideran parte de ambas ramas cuando se fusiona la rama característica. Incluso hay un comando para verificar eso:
Además, las sucursales son baratas, locales y etéreas; se pueden agregar, eliminar, renombrar, enviar y eliminar fácilmente del servidor.
Git sigue el principio de que todo se puede hacer, por lo que puede eliminar fácilmente una rama de un servidor remoto y puede reescribir fácilmente el historial.
Digamos que estaba en la rama 'maestra', e hice dos confirmaciones: 'hacer café' y 'agregar leche y azúcar', luego decido usar una nueva rama para eso, así que restablezco 'maestra' a 'origen /Maestro'. No es un problema, toda la historia aún está limpia: 'preparar café' y 'agregar leche y azúcar' no son parte del maestro, solo tienen función / hacen café.
Mercurial es lo contrario; No quiere cambiar las cosas. Las ramas son permanentes, el historial de reescritura está mal visto, no se puede simplemente eliminar una rama del servidor.
En resumen: Git te permite hacer todo, Mercurial quiere facilitar las cosas (y hace que sea realmente difícil dejarte hacer lo que quieras).
fuente