Como você consegue um esquema de versão numérica com o Git?


131

Minha organização está considerando mudar do SVN para o Git. Um argumento contra a movimentação é o seguinte:

Como fazemos o versionamento?

Temos uma distribuição SDK baseada na plataforma NetBeans. Como as revisões do SVN são números simples, podemos usá-las para estender os números de versão de nossos plug-ins e compilações do SDK. Como lidamos com isso quando nos mudamos para o Git?

Soluções possíveis:

  • Usando o número da compilação do Hudson (Problema: você precisa verificar o Hudson para correlacioná-lo a uma versão real do Git)
  • Atualizando manualmente a versão para noturno e estável (Problema: Curva de aprendizado, erro humano)

Se alguém encontrou um problema semelhante e o resolveu, gostaríamos de saber como.


3
Você poderia fazer com que seu servidor hudson (não jenkins ?) Adicione automaticamente uma gittag após cada compilação bem-sucedida? Isso teria a vantagem adicional de deixar bem claro quais gitconfirmações têm problemas de compilação ou falhas de teste, uma vez que permaneceriam sem marcação.
Mark Booth


Como observação lateral, você pode adicionar a contagem de compilação à tag acompanhando os tempos de compilação .
Shahbaz

Não tenho certeza se é uma solução viável, mas que tal exportar do git para um repositório svn antes de cada compilação? Em seguida, basta criar a partir do repositório svn - se o que queremos é centralizado, basta usá-lo.
Jonny

Respostas:


152

Use tags para marcar confirmações com números de versão:

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

Push tags upstream - isso não é feito por padrão:

git push --tags

Em seguida, use o comando de descrição :

git describe --tags --long

Isso fornece uma sequência do formato:

v2.5-0-gdeadbee
^    ^ ^^
|    | ||
|    | |'-- SHA of HEAD (first seven chars)
|    | '-- "g" is for git
|    '---- number of commits since last tag
|
'--------- last tag

Concordo - deve ser fácil automatizar a numeração noturna de tags, se você precisar, e a promoção para estável é manual de qualquer maneira.
Inútil

20
Melhoria pequena: git describe --long --tags --dirty --always. 'Dirty' dirá se houve alterações locais quando a 'descrição' foi feita (o que significa que não pode descrever completamente o estado do repo). "Sempre" significa que você não receberá um erro quando não houver tags. Ele fará o fallback para apenas um hash de confirmação. Então você pode obter 76001f2-dirtycomo exemplo. Obviamente, ver 'sujo' significa que alguém estragou tudo.
Mike Weller

1
Como isso pode funcionar quando a tag é gerada pela última vez . Normalmente, você deseja que as construções a seguir tenham a próxima versão do seu produto. Mas eles sempre serão forçados a usar a última versão neste caso. Somente a versão final, enviada, terá o número adequado.
precisa saber é o seguinte

@ void.pointer: Claro, este número de versão responde à pergunta “em qual versão este commit foi baseado?” e não “em qual release este commit estará?” No entanto, você pode interpretar as tags de maneira diferente. Por exemplo, se você marcar HEADcomo v2.5, também poderá interpretá-lo como o início do ciclo de lançamento do 2.5 e depois marcar v2.5-releaseou o que quiser.
Jon Purdy

8
Outra pequena melhoria. Se você quiser ter outras tags também, mas usar uma tag padronizada especificamente para a geração de revisões, poderá usar a --matchopção assim:git describe --long --tags --dirty --always --match 'v[0-9]\.[0-9]'
Alexander Amelkin

42

Isso surgiu em alguns projetos para mim. A melhor solução que eu tive até agora é gerar um número de versão como este:

xy <número de confirmações> .r <git-hash>

Normalmente, é gerado pelo nosso sistema de compilação usando uma combinação de algum arquivo ou tag estático para obter os principais números de revisão git rev-list HEAD | wc -l(que foi mais rápido do que usar git log) e git rev-parse HEAD. O raciocínio foi o seguinte:

  1. Precisávamos que a versão de alto nível acontecesse explicitamente (iexy)
  2. Quando o desenvolvimento paralelo estava acontecendo, NUNCA precisávamos gerar o mesmo número de versão.
  3. Queríamos rastrear facilmente de onde veio uma versão.
  4. Quando as linhas paralelas foram mescladas, queríamos que a nova versão resolvesse mais alto do que qualquer uma das ramificações.

O número 2 é invisível para a maioria das pessoas, mas é realmente importante e muito difícil com o controle de fonte distribuído. O SVN ajuda nisso, fornecendo um único número de revisão. Acontece que uma contagem de confirmação é o mais próximo possível, enquanto magicamente resolve o número 4. Na presença de ramificações, isso ainda não é exclusivo; nesse caso, adicionamos o hash, que também resolve o problema # 3.

A maior parte disso foi para acomodar a implantação via pip do Python. Isso garantiu que pip installtalvez fosse um pouco estranho durante o desenvolvimento paralelo (ou seja, pacotes de pessoas em diferentes ramos se misturariam, mas de maneira determinística), mas que, após a fusão, tudo se resolveu. Exceto a presença de uma rebase ou alteração exposta, isso funcionou muito bem para os requisitos acima.

Caso você esteja se perguntando, optamos por colocar r na frente do hash devido a alguma estranheza na maneira como o pacote Python lida com letras nos números de versão (ou seja, ae é menor que 0, o que tornaria "1.3.10.a1234" < "1.3.10" <"1.3.10.1234").


1
btw, como você lidou com o problema dos ovos de galinha de determinar o hash git antes de fazer o check-in? Você usou alguma forma de .gitignore ou algum outro truque?
kfmfe04

3
Eu não fiz. Eu não uso o hash até o tempo de compilação do pacote, que é muito tempo após o check-in. Idiomas diferentes têm maneiras diferentes de injetar isso. Para Python, eu uso './setup.py egg_info -b ". $ {BUILD_VERSION}" sdist'. Para C e C ++, defino uma macro em tempo de compilação com 'CFLAGS = -D "$ {BUILD_VERSION}"'. Para o Go, defino um símbolo no momento do link com 'go install -ldflags appmodule.BuildVersion "-X. $ {BUILD_VERSION}"'.
Jayson

1
Essa deve ser a melhor resposta.
alvinabad

resposta muito boa
haelix 18/09/18

9

Isso pode ser um pouco exagerado, mas informarei como o fazemos.

Usamos uma estrutura de ramificação muito semelhante a isso .

O Hudson cria nossas ramificações "desenvolvidas" e aumenta os números de compilação a partir de 0. O número da compilação é exclusivo para cada projeto e é marcado no controle de versão. O motivo é para que você possa dizer exatamente de qual criação de ramificação de desenvolvimento 42 veio, por exemplo (cada projeto pode ter várias ramificações de desenvolvimento em paralelo, porque cada projeto pode ter várias equipes trabalhando em diferentes aspectos do projeto).

Quando decidimos que uma compilação específica é boa o suficiente para ser liberada, a confirmação que acionou essa compilação é marcada com um número de versão da release, que é decidido pelo marketing. Isso significa que as equipes de desenvolvimento não se importam com o número da versão final e o marketing é livre para alternar entre os números de versão como entender. O número da versão final e o número da compilação estão presentes no produto lançado.

Exemplo: 2.1.0 build 1337

Isso significa que, para uma versão específica do produto, você pode dizer qual foi a última equipe a trabalhar nela e pode consultar o git para todas as confirmações que antecederam a liberação para diagnosticar um problema, se necessário.


8

As versões são identificadas com hash SHA1 de todos os arquivos na árvore de diretórios armazenados no momento do check-in. Esse hash é armazenado juntamente com os hashes do (s) check-in (s) pai (s), para que o histórico completo possa ser lido.

Dê uma olhada no processo de usar 'git-description' por meio do GIT-VERSION-GEN e como você pode adicionar isso através do processo de compilação ao marcar seu release.

Aqui está um bom blog que fornece um exemplo de como obter o que você deseja:

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


0

Jon Purdy tem a ideia certa. git flowfacilita também o gerenciamento real dessas filiais, e o gerenciamento de filiais é um argumento para mudar para git.

Vamos começar com um resumo básico de git, desde que você está vindo do svnPara- gitperspectiva. Considere gito seguinte:

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

Acima, você ramifica masterpara develop(indicado por \) e ramifica developpara uma featureramificação. Mesclamos esses ramos de backup (denotados por /), com commits ( -) ao longo de um ramo. (Se não houver confirmação, mas a mesclagem estiver na direita, há .indicadores para mostrar que a próxima -é a próxima confirmação).

Bastante fácil. E se tivermos um hotfix em nossa versão principal?

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

Acima, developramificado de master. O bug descoberto em masterfoi corrigido ramificando-o master, corrigindo-o e mesclando-o novamente master. Em seguida, fundiu masterpara develop, em seguida, developemfeature2 que rolou o novo código de hotfixdentro desses ramos.

Quando você mescla feature2de volta para develop, a sua história inclui developo hotfix. Da mesma forma, developé mesclado feature2com o novo código de master, portanto, mesclar de developvolta para masteracontecerá sem problemas, pois ele é baseado nesse commit masternaquele momento - como se você tivesse ramificado masternaquele momento.

Então, aqui está outra maneira de fazer isso.

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

Suas 1.0 lançamentos obter tagged- 1.0.1, 1.0.2, 1.0.3, e assim por diante.

Agora, aqui está um truque: você encontrou um bug na versão 1.0 e afeta 1.1, 1.2 e 1.3. O que você faz?

Você ramifica a versão mais recente ou mais antiga mantida e a corrige. Então você mesclar seu novo hotfixramo em 1.3-e em 1.2, 1.1, e 1.0. Não ramifique de cada uma das ramificações da versão de manutenção; não se fundem 1.0em masterou fundir masterpara trás em 1.0. Pegue o único hotfixramo e mescle-o em todos os seus ramos de versão. Se houver conflitos, será informado; revise seu código para garantir que as alterações estejam corretas ( git diffé seu amigo).

Agora essa mudança específica é aplicada em qualquer lugar. A linhagem é ramificada, mas está tudo bem. Não é casual. Marque a 1.3cabeça como 1.3.17, mescle-a em todos os recursos em andamento ramificados 1.3e siga em frente.

A git flowextensão ajuda a gerenciar essas ramificações de manutenção, recursos e hotfix para você. Depois de baixar o fluxo de trabalho, isso é trivial e gera uma enorme quantidade de problemas no gerenciamento de código-fonte.

Já vi isso nas equipes de programação, mas também não trabalhei tão profundamente como programador; portanto, ainda estou estudando o fluxo de trabalho do dia-a-dia.


-6

O Pro Git na seção 7.2 "Atributos Git" na parte de expansão "Palavra-chave" contém um bom exemplo de uso de filtros de manchas e limpeza para gerar palavras-chave no estilo RCS. Você pode usar a mesma técnica para incorporar alguma string de versão no código, formatado e calculado de acordo com suas regras . Você ainda pode usar git describecomo ponto de partida, mas tem a possibilidade de se transformar em qualquer forma mais apropriada e obter da versão 2.5-14-14, por exemplo, limpar 2.5.14


9
-1 por arruinar uma boa resposta com ataques desnecessários para ad hominem.
Jörg W Mittag

9
Quem diria que eram garotos de pau votando em você. Poderia facilmente ser pessoas que preferem um pouco de civilidade .
Mark Booth

Para sua informação, acabei de editar a resposta.
Keith Thompson

git describegera o nome da tag, a menos que --longseja passado ou haja confirmações desde a última tag, portanto já está perfeitamente limpo. Se você não estivesse alterando os padrões, isso lhe daria exatamente o que você queria.
strcat
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.