Comment réaliser un schéma de version numérique avec Git?

131

Mon organisation envisage de passer de SVN à Git. Un argument contre le déménagement est le suivant:

Comment fait-on le versioning?

Nous avons une distribution SDK basée sur la plate-forme NetBeans. Comme les révisions SVN sont de simples nombres, nous pouvons les utiliser pour étendre les numéros de version de nos plugins et versions de SDK. Comment gérons-nous cela lorsque nous déménageons à Git?

Solutions possibles:

  • Utiliser le numéro de build de Hudson (Problème: vous devez vérifier Hudson pour le corréler avec une version réelle de Git)
  • Amélioration manuelle de la version de nuit et stable (Problème: courbe d’apprentissage, erreur humaine)

Si quelqu'un d'autre a rencontré un problème similaire et l'a résolu, nous aimerions savoir comment.

Erlend
la source
3
Pourriez-vous demander à votre serveur hudson (pas jenkins ?) D’ajouter automatiquement une gitbalise après chaque construction réussie? Cela présenterait l'avantage supplémentaire d'indiquer clairement les gitcommits présentant des problèmes de construction ou d'échecs de test, car ils resteraient non étiquetés.
Mark Booth
En guise de remarque, vous pouvez ajouter le nombre de générations à la balise en suivant les temps de génération .
Shahbaz
Pas sûr de savoir si une solution viable, mais que diriez-vous d'exporter de git vers un svn repo juste avant chaque construction? Ensuite, construisez simplement à partir du rapport svn - si centralisé est ce que nous voulons, utilisez-le à la place.
Jonny

Réponses:

152

Utilisez des balises pour marquer les commits avec des numéros de version:

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

Balises Push en amont - cela n'est pas fait par défaut:

git push --tags

Ensuite, utilisez la commande describe :

git describe --tags --long

Cela vous donne une chaîne du format:

v2.5-0-gdeadbee
^    ^ ^^
|    | ||
|    | |'-- SHA of HEAD (first seven chars)
|    | '-- "g" is for git
|    '---- number of commits since last tag
|
'--------- last tag
Jon Purdy
la source
D'accord - il devrait être facile d'automatiser la numérotation des étiquettes tous les soirs si vous en avez besoin, et la promotion de stable est manuelle.
Inutile
20
Petite amélioration: git describe --long --tags --dirty --always. "Sale" vous dira s'il y a eu des changements locaux lorsque la "description" a été effectuée (ce qui signifie qu'elle ne peut pas décrire complètement l'état du référentiel). "Toujours" signifie que vous ne recevrez pas d'erreur en l'absence de balises. Il se réduira à un simple hachage de commit. Donc, vous pouvez avoir 76001f2-dirtycomme exemple. De toute évidence, voir «sale» signifie que quelqu'un a tout gâché.
Mike Weller
1
Comment cela peut-il fonctionner lorsque la balise est générée en dernier . Normalement, vous souhaitez que les versions ultérieures aient la prochaine version de votre produit. Mais ils seront toujours obligés d'utiliser la dernière version dans ce cas. Seule la version finale livrée aura le numéro approprié.
void.pointer
@ void.pointer: Bien sûr, ce numéro de version répond à la question "Sur quelle version cette validation a-t-elle été basée?" et non "dans quelle version cette validation sera-t-elle?" Cependant, vous êtes libre d'interpréter les balises différemment. Par exemple, si vous marquez en HEADtant que v2.5, vous pouvez aussi bien interpréter cela comme le début du cycle de publication de la version 2.5, puis marquer v2.5-releaseou ce que vous préférez.
Jon Purdy
8
Une autre petite amélioration. Si vous souhaitez également utiliser d'autres balises, mais utilisez une balise à motif spécifique pour la génération de révision, vous pouvez utiliser l' --matchoption suivante:git describe --long --tags --dirty --always --match 'v[0-9]\.[0-9]'
Alexander Amelkin
42

Cela est arrivé sur quelques projets pour moi. La meilleure solution que j'ai eu jusqu'à présent est de générer un numéro de version comme celui-ci:

xy <nombre de commits> .r <git-hash>

Généralement, il est généré par notre système de construction en combinant un fichier statique ou une balise pour obtenir les numéros de révision majeurs git rev-list HEAD | wc -l(ce qui était plus rapide que l’utilisation git log), et git rev-parse HEAD. Le raisonnement était le suivant:

  1. Nous avions besoin de la possibilité d'avoir un versioning de haut niveau se produire explicitement (iexy)
  2. Lorsque le développement parallèle se produisait, nous devions ne jamais générer le même numéro de version.
  3. Nous voulions savoir facilement d'où venait une version.
  4. Lorsque les lignes parallèles ont été fusionnées, nous voulions que la nouvelle version résolve plus haut que l'une des branches.

Le numéro 2 est invisible pour la plupart des gens, mais il est vraiment important et très difficile avec le contrôle de source distribué. SVN vous aide en vous donnant un numéro de révision unique. Il s'avère que le nombre de validations est aussi proche que possible, tout en résolvant magiquement la # 4 également. En présence de branches, cela n’est pas encore unique, auquel cas nous ajoutons le hachage, qui résout parfaitement le problème n ° 3.

La plupart de ces opérations étaient destinées au déploiement via le pip de Python. Cela garantissait que cela pip installserait peut-être un peu étrange lors du développement parallèle (par exemple, les paquets de personnes de différentes branches se mêleraient, mais de manière déterministe), mais qu'après la fusion, tout serait réglé. Sauf présence d'un rebase exposé ou d'une modification, cela fonctionnait assez bien pour les exigences ci-dessus.

Au cas où vous vous le demanderiez, nous avons choisi de mettre le r devant le hachage en raison d'un étrange problème avec la façon dont les emballages Python traitent les lettres avec des numéros de version (c'est-à-dire ae sont inférieurs à 0, ce qui ferait "1.3.10.a1234" < "1.3.10" <"1.3.10.1234").

Jayson
la source
1
Au fait, comment avez-vous géré le problème de la détermination du git-hash avant de vous enregistrer? Avez-vous utilisé une forme de .gitignore ou une autre astuce?
kfmfe04
3
Je n'ai pas. Je n'utilise pas le hachage jusqu'au moment de la création du paquet, ce qui est long après l'enregistrement. Différentes langues ont différentes façons d'injecter cela. Pour Python, j'utilise './setup.py egg_info -b ". $ {BUILD_VERSION}" sdist ". Pour C et C ++, je définis une macro à la compilation avec 'CFLAGS = -D "$ {BUILD_VERSION}"'. Pour Go, je définis un symbole au moment de la liaison avec 'go install -ldflags appmodule.BuildVersion "-X. $ {BUILD_VERSION}"'.
Jayson
1
Cela devrait être la meilleure réponse.
Alvinabad
très bonne réponse
haelix
9

C'est peut-être un peu exagéré, mais je vous ferai savoir comment nous le faisons.

Nous utilisons une structure de branchement très similaire à celle-ci .

Hudson construit à partir de 0 nos branches de développement et incrémente les numéros de build. Le numéro de build est unique pour chaque projet et est marqué dans le contrôle de version. La raison en est que vous pouvez savoir exactement de quelle branche de développement est issu 42 (chaque projet peut avoir plusieurs branches de développement en parallèle, car chaque projet peut avoir plusieurs équipes travaillant sur différents aspects du projet).

Lorsque nous décidons qu'une version particulière est suffisamment bonne pour être publiée, la validation qui a déclenché cette génération est identifiée par un numéro de version, qui est décidé par le marketing. Cela signifie que les équipes de développement ne se soucient pas du numéro de version final et que le marketing est libre de modifier les numéros de version à sa guise. Le numéro de version final et le numéro de build sont tous deux présents dans le produit publié.

Exemple: 2.1.0 build 1337

Cela signifie que, pour une version de produit spécifique, vous pouvez déterminer quelle est la dernière équipe à avoir travaillé dessus et vous pouvez interroger git pour tous les validations menant à la publication afin de diagnostiquer un problème le cas échéant.

Carl
la source
8

Les versions sont identifiées en hachant les hachages SHA1 de tous les fichiers de l'arborescence de répertoires stockés au moment de l'archivage. Ce hachage est stocké à côté des hachages du ou des archivages parent afin que l'historique complet puisse être lu.

Examinez le processus d'utilisation de 'git-describe' via GIT-VERSION-GEN et comment vous pouvez l'ajouter via votre processus de construction lorsque vous balisez votre version.

Voici un joli blog qui donne un exemple de comment obtenir ce que vous voulez:

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

Logiciel menuisier
la source
0

Jon Purdy a la bonne idée. git flowLa gestion réelle de ces succursales est également facile, et la gestion des succursales est un argument en faveur de la transition git.

Commençons par une diminution des effectifs de base git, puisque vous venez de la svn-à- gitperspective. Considérons dans gitce qui suit:

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

Ci-dessus, vous branchez mastervers develop(indiqué par le \) et branchez developvers une featurebranche. Nous fusionnons ces branches (notées par /), avec commits ( -) le long d’une branche. (S'il n'y a pas de commit mais que la fusion va très à droite, il y a des .indicateurs pour montrer que le prochain -est le prochain commit).

Assez facile. Et si nous avons un correctif dans notre version principale?

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

Ci-dessus, developramifié de master. Le bogue découvert dans a masterété corrigé en séparant master, en le corrigeant et en le fusionnant master. Nous avons ensuite fusionné masterdans develop, puis developdansfeature2 , qui a intégré le nouveau code hotfixdans ces branches.

Lorsque vous fusionnez feature2à develop, son histoire inclut developavec le hotfix. De même, developest fusionné feature2avec le nouveau code de master, si la fusion de developretour à masterva se passer sans accroc, car il est basé sur cette livraison en masterà ce moment - là, comme si vous aviez ramifié à partir masterà ce moment - là.

Alors, voici une autre façon de le faire.

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

Vos 1.0 versions se tagged- 1.0.1, 1.0.2, 1.0.3, et ainsi de suite.

Maintenant, voici une astuce: vous avez trouvé un bogue dans la version 1.0 qui affecte les versions 1.1, 1.2 et 1.3. Que faire?

Vous branchez votre version la plus récente ou la plus ancienne maintenue et vous la corrigez. Ensuite , vous fusionnez votre nouvelle hotfixbranche en 1.3-et dans 1.2, 1.1et 1.0. Ne branchez pas depuis chacune des branches de la version de maintenance; ne fusionnez pas 1.0dans masterou ne fusionnez masterpas dans 1.0. Prenez une hotfixbranche et fusionnez-la dans toutes vos branches de version. S'il y a des conflits, cela vous le dira; révisez votre code pour vous assurer que les modifications sont correctes ( git diffest votre ami).

Maintenant, ce changement spécifique est appliqué partout. La lignée est ramifiée, mais ça va. Ce n'est pas un hasard. 1.3Marquez la tête en tant que 1.3.17, fusionnez-la dans chaque fonction en cours reliée 1.3et passez à autre chose.

L' git flowextension permet de gérer ces branches de maintenance, de fonctionnalités et de correctifs pour vous. Une fois que vous maîtrisez le flux de travail, cette opération est simple et simplifie énormément la gestion du code source.

J'ai déjà vu cela dans les équipes de programmation, mais je n'ai pas travaillé autant en tant que programmeur moi-même. Je suis donc en train de me familiariser avec le flux de travail quotidien.

John Moser
la source
-6

Pro Git dans la section 7.2 "Attributs Git" dans "Mot-clé" La partie Expansion contient un bel exemple d'utilisation de filtres smudge & clean pour générer des mots-clés de style RCS. Vous pouvez utiliser la même technique pour incorporer une chaîne de version quelconque dans du code, formaté et calculé en fonction de vos règles . Vous pouvez toujours l' utiliser git describecomme point de départ, mais vous avez la possibilité de passer à une forme plus appropriée et d'obtenir de v2.5-14-feebdaed, par exemple, clean 2.5.14

Badger paresseux
la source
9
-1 pour avoir ruiné une bonne réponse avec des attaques ad hominem complètement non appelées.
Jörg W Mittag
9
Qui est-ce qui a dit que c'étaient des git boys qui ont voté contre vous? Ce pourrait être facilement des gens qui préfèrent un peu de civilité .
Mark Booth
FYI, je viens de modifier la réponse.
Keith Thompson
git describesort le nom de la balise à moins que ce ne --longsoit passé ou qu'il y ait des commits depuis la dernière balise, donc c'est déjà parfaitement propre. Si vous ne changiez pas les valeurs par défaut, cela vous aurait donné exactement ce que vous vouliez.
Strcat