¿Cómo se logra un esquema de versiones numéricas con Git?

131

Mi organización está considerando mudarse de SVN a Git. Un argumento contra el movimiento es el siguiente:

¿Cómo hacemos versiones?

Tenemos una distribución de SDK basada en la plataforma NetBeans. Como las revisiones de SVN son números simples, podemos usarlas para extender los números de versión de nuestros complementos y compilaciones de SDK. ¿Cómo manejamos esto cuando nos mudamos a Git?

Soluciones posibles:

  • Usando el número de compilación de Hudson (Problema: debe verificar Hudson para correlacionarlo con una versión Git real)
  • Actualización manual de la versión para noche y estable (Problema: curva de aprendizaje, error humano)

Si alguien más ha encontrado un problema similar y lo resolvió, nos encantaría saber cómo.

Erlend
fuente
3
¿Podría hacer que su servidor hudson (no jenkins ?) Agregue automáticamente una gitetiqueta después de cada compilación exitosa? Esto tendría la ventaja adicional de que deja muy claro qué gitcommits tienen problemas de compilación o fallas de prueba, ya que permanecerían sin etiquetar.
Mark Booth
Como nota al margen, puede agregar el recuento de compilación a la etiqueta mediante el seguimiento de los tiempos de compilación .
Shahbaz
No estoy seguro de si es una solución viable, pero ¿qué hay de exportar de git a un repositorio svn justo antes de cada compilación? Luego, simplemente construya desde el repositorio svn: si lo centralizado es lo que queremos, solo use eso en su lugar.
Jonny

Respuestas:

152

Use etiquetas para marcar confirmaciones con números de versión:

git tag -a v2.5 -m 'Version 2.5'

Empuje las etiquetas en sentido ascendente: esto no se hace de manera predeterminada:

git push --tags

Luego use el comando describe :

git describe --tags --long

Esto le da una cadena del formato:

v2.5-0-gdeadbee
^    ^ ^^
|    | ||
|    | |'-- SHA of HEAD (first seven chars)
|    | '-- "g" is for git
|    '---- number of commits since last tag
|
'--------- last tag
Jon Purdy
fuente
De acuerdo: debería ser fácil automatizar la numeración nocturna de etiquetas si lo necesita, y la promoción a estable es manual de todos modos.
Inútil
20
Pequeña mejora: git describe --long --tags --dirty --always. 'Sucio' le dirá si hubo cambios locales cuando se realizó la 'descripción' (lo que significa que no puede describir completamente el estado del repositorio). "Siempre" significa que no recibirá un error cuando no haya etiquetas. Se recurrirá a solo un hash de confirmación. Entonces puedes obtener 76001f2-dirtycomo ejemplo. Obviamente, ver "sucio" significa que alguien se equivocó.
Mike Weller
1
¿Cómo puede funcionar esto cuando la etiqueta se genera por última vez ? Normalmente desea que las compilaciones en adelante tengan la próxima versión de su producto. Pero siempre se verán obligados a usar la última versión en este caso. Solo la construcción final enviada tendrá el número adecuado.
void.pointer
@ void.pointer: Claro, este número de versión responde a la pregunta "¿en qué versión se basó esta confirmación?" y no "¿en qué versión estará esta confirmación?" Sin embargo, puede interpretar las etiquetas de manera diferente. Por ejemplo, si etiqueta HEADcomo v2.5, puede interpretarlo como el inicio del ciclo de lanzamiento 2.5, luego etiquetar v2.5-releaseo lo que quiera.
Jon Purdy
8
Otra pequeña mejora. Si desea tener otras etiquetas también, pero usa una etiqueta con un patrón específico para la generación de revisión, puede usar la --matchopción de esta manera:git describe --long --tags --dirty --always --match 'v[0-9]\.[0-9]'
Alexander Amelkin
42

Esto ha surgido en algunos proyectos para mí. La mejor solución que he tenido hasta ahora es generar un número de versión como este:

xy <número de confirmaciones> .r <git-hash>

Por lo general, es generado por nuestro sistema de compilación utilizando una combinación de algún archivo o etiqueta estática para obtener los números de revisión principales git rev-list HEAD | wc -l(que fue más rápido que el uso git log) y git rev-parse HEAD. El razonamiento fue el siguiente:

  1. Necesitábamos la capacidad de que las versiones de alto nivel ocurrieran explícitamente (iexy)
  2. Cuando ocurría un desarrollo paralelo, NUNCA necesitábamos generar el mismo número de versión.
  3. Queríamos rastrear fácilmente de dónde vino una versión.
  4. Cuando se fusionaron líneas paralelas, queríamos que la nueva versión se resolviera más alto que cualquiera de las ramas.

El número 2 es invisible para la mayoría de las personas, pero es realmente importante y muy difícil con el control de fuente distribuida. SVN ayuda con esto al darle un solo número de revisión. Resulta que un recuento de confirmación es lo más cercano posible, mientras que mágicamente resuelve el # 4 también. En presencia de ramas, esto aún no es único, en cuyo caso agregamos el hash, que también resuelve perfectamente el n. ° 3.

La mayor parte de esto fue para acomodar el despliegue a través del pip de Python. Esto garantizó que pip installtal vez sería un poco extraño durante el desarrollo paralelo (es decir, los paquetes de personas en diferentes ramas se mezclarían, pero de manera determinista), pero que después de las fusiones, todo se resolvió. Salvo la presencia de un rebase o enmienda expuesto, esto funcionó bastante bien para los requisitos anteriores.

En caso de que se lo pregunte, elegimos poner la r delante del hash debido a alguna rareza con la forma en que el empaque de Python maneja las letras en los números de versión (es decir, ae son menores que 0, lo que haría "1.3.10.a1234" < "1.3.10" <"1.3.10.1234").

Jayson
fuente
1
por cierto, ¿cómo lidiaste con el problema del huevo de gallina de determinar el git-hash antes de registrarlo? ¿Usaste alguna forma de .gitignore o algún otro truco?
kfmfe04
3
No lo hice No uso el hash hasta el tiempo de compilación del paquete, que es mucho después del check-in. Diferentes idiomas tienen diferentes formas de inyectar esto. Para Python, uso './setup.py egg_info -b ". $ {BUILD_VERSION}" sdist'. Para C y C ++, defino una macro en tiempo de compilación con 'CFLAGS = -D "$ {BUILD_VERSION}"'. Para Go, defino un símbolo en el momento del enlace con 'go install -ldflags appmodule.BuildVersion "-X. $ {BUILD_VERSION}"'.
Jayson
1
Esta debería ser la mejor respuesta.
alvinabad
muy buena respuesta
haelix
9

Esto puede ser un poco exagerado, pero le diré cómo lo hacemos.

Usamos una estructura de ramificación muy similar a esta .

Hudson se basa en nuestras ramas de "desarrollo" e incrementa los números de compilación a partir de 0. El número de compilación es único para cada proyecto y se etiqueta en el control de versiones. La razón es para que pueda saber exactamente de qué rama de desarrollo surgió la compilación 42, por ejemplo (cada proyecto puede tener varias ramas de desarrollo en paralelo, porque cada proyecto puede tener varios equipos trabajando en diferentes aspectos del proyecto).

Cuando decidimos que una compilación en particular es lo suficientemente buena como para ser lanzada, la confirmación que activó esa compilación se etiqueta con un número de versión de lanzamiento, que se decide por marketing. Esto significa que los equipos de desarrollo no se preocupan por cuál es el número de versión final y que el marketing es libre de barajar los números de versión como mejor le parezca. El número de versión final y el número de compilación están presentes en el producto lanzado.

Ejemplo: 2.1.0 compilación 1337

Esto significa que, para un lanzamiento de producto específico, puede saber cuál fue el último equipo que trabajó en él y puede consultar en git todas las confirmaciones previas al lanzamiento para diagnosticar un problema si es necesario.

Carl
fuente
8

Las versiones se identifican con el hash SHA1 de todos los archivos en el árbol de directorios almacenado en el momento del registro. Este hash se almacena junto con los hash de los registros principales para que se pueda leer el historial completo.

Eche un vistazo al proceso de uso de 'git-describe' a través de GIT-VERSION-GEN y cómo puede agregar esto a través de su proceso de compilación cuando etiquete su lanzamiento.

Aquí hay un buen blog que da un ejemplo de cómo obtener lo que quieres:

http://cd34.com/blog/programming/using-git-to-generate-an-automatic-version-number/

SoftwareCarpenter
fuente
0

Jon Purdy tiene la idea correcta. git flowfacilita también la gestión real de estas sucursales, y la gestión de sucursales es un argumento para avanzar git.

Vamos a empezar con un resumen básico de git, ya que está viniendo de la svn-a- gitperspectiva. Considere en gitlo siguiente:

master--...............-.....-..............-
        \             /     /              /
         ---develop---------............../
                            \            /
                             --feature---

Arriba, se ramifica mastera develop(denotado por \) y se ramifica developa una featurerama. Fusionamos esas ramas nuevamente (denotadas por /), con commits ( -) a lo largo de una rama. (Si no hay confirmación, pero la combinación está a la derecha, hay .indicadores que muestran que la siguiente -es la siguiente confirmación).

Suficientemente fácil. ¿Qué pasa si tenemos una revisión en nuestra versión principal?

master--...............-.....-................-...........-.........-
        \             /     /                / \         /|        /
         \           /     /                /   -hotfix-- V       /
          ---develop---------............../..............-...----
                             \            / \             V   /
                              --feature---   --feature2...----

Arriba, developramificado de master. El error descubierto en masterse solucionó ramificándose desde master, arreglándolo y fusionándose nuevamente master. Luego nos fusionamos mastercon develop, y luego developconfeature2 , que rodaron el nuevo código desde hotfixestas ramas.

Cuando feature2vuelve a fusionarse develop, su historia incluye developcon el hotfix. Del mismo modo, developse fusionó feature2con el nuevo código de master, por lo que la fusión developvolverá a masterocurrir sin problemas, ya que se basa en esa confirmación en masterese momento, como si se hubiera bifurcado desde masterese punto.

Así que aquí hay otra forma de hacerlo.

master--..........-........-
        \        /\       /
         ---1.0--  --1.1-- 

Sus publicaciones Get 1.0 tagged- 1.0.1, 1.0.2, 1.0.3, y así sucesivamente.

Ahora, aquí hay un truco: encontró un error en 1.0 y afecta a 1.1, 1.2 y 1.3. ¿Qué haces?

Bifurcas tu última versión mantenida o la anterior y la reparas. A continuación, combinar su nueva hotfixsucursal en 1.3-y en 1.2, 1.1, y 1.0. No ramifique desde cada una de las ramificaciones de la versión de mantenimiento; no fusionar 1.0en mastero fusionar masterde nuevo en 1.0. Tome la hotfixrama única y únala en todas las ramas de su versión. Si hay conflictos, te lo dirá; revise su código para asegurarse de que los cambios sean correctos ( git diffes su amigo).

Ahora ese cambio específico se aplica en todas partes. El linaje es ramificado, pero está bien. No es casual. Etiquete la 1.3cabeza como 1.3.17, combínela en cada característica en progreso ramificada desde 1.3y continúe.

La git flowextensión ayuda a administrar estas ramas de mantenimiento, características y revisiones por usted. Una vez que baja el flujo de trabajo, esto es trivial y elimina una gran cantidad de problemas de la administración del código fuente.

He visto esto en equipos de programación, pero yo no he trabajado tan profundamente como programador, así que todavía estoy entendiendo el flujo de trabajo diario.

John Moser
fuente
-6

Pro Git en la sección 7.2 "Atributos de Git" en la parte de expansión "Palabra clave" contiene un buen ejemplo del uso de filtros borrosos y limpios para generar palabras clave de estilo RCS. Puede utilizar la misma técnica para incrustar alguna cadena de versión en el código, formateada y calculada de acuerdo con sus reglas . Todavía puede usarlo git describecomo punto de partida, pero tiene la posibilidad de transformarse a cualquier forma más apropiada y obtener de v2.5-14-feebdaed, por ejemplo, clean 2.5.14

Tejón perezoso
fuente
99
-1 por arruinar una buena respuesta con ataques de hominem completamente inadvertidos.
Jörg W Mittag
99
Quién puede decir que fueron git-boys rechazándote. Podría ser fácilmente gente que prefiere un poco de cortesía .
Mark Booth
FYI, acabo de editar la respuesta.
Keith Thompson
git describegenera el nombre de la etiqueta a menos que --longse pase o haya confirmaciones desde la última etiqueta, por lo que ya está perfectamente limpio. Si no estuviera cambiando los valores predeterminados, le habría dado exactamente lo que quería.
strcat