如何在Git中管理版本号?

103
让我们想象一下,blerp 命令行工具在 上得到维护。该工具有一个(隐藏的)--version 选项,返回其 版本(假设为 0.1.2),还有另一个 --commit,返回它构建时的提交号。
版本和提交号都是硬编码到代码库中的。
现在我进行了一个 bugfix,然后提交并重新构建我的程序。尽管这个新版本与原始的 0.1.2 不同,但我仍然会看到 0.1.2。只有提交才会告诉我它不是相同的 0.1.2。这个 bugfix 值得一个不同的版本号吗?
一种解决方案是每次提交时增加硬编码版本号(这意味着每次提交至少修改两个文件)。这是一种约束性的解决方案,当开发人员在不同的活动分支上工作时无法使用。如果Bob从版本0.1.2开始使用功能foo,而Alice从相同版本的功能bar开始工作,他们如何增加版本号?Bob可以使用奇数,而Alice可以使用偶数。如果Eve正在开发第三个功能呢?
另一种解决方案是使用Git标签自动生成版本号。脚本可以找到以v开头的最接近的标签,例如v0.1.2,并将标签名称用作版本号加上当前提交的前n位数字(v0.1.2(build 4acd21))。如果工作目录干净,则此方法有效。可以想象在构建号之前添加*以表示工作目录不干净。此解决方案的主要问题是如果有人导出源代码,则无法构建blerp
有什么可能的替代方案来解决这个问题?

9
通常情况下,应避免将版本信息放入源代码文件中。最好的方式是使用构建过程将版本信息编码到构建号中,这样版本信息就与用于构建的源代码无关。该过程还可以在某处编码提交编号,因此您始终知道从哪个源代码进行了构建。至于存储版本号,常见的解决方案是使用标签。这也使您可以通过查看标签轻松浏览您的代码库中的不同版本。 - poke
@poke 如果你只有源代码,没有版本控制系统,那么如何获取产品的版本号呢?blerp的版本号是什么? - nowox
1
通常情况下,您发布的内容与版本控制中的内容并不完全相同。因此,您可以按照我所描述的方式在构建过程中应用版本。 - poke
2
我知道这是一个旧问题,但我制作了一个脚本,它可以进行一些版本管理以及更多功能:https://github.com/jv-k/bump-version.sh - jv-k
5个回答

202

Alexey KiselevDario已经提到了答案,但我会尽量详细地解释。

版本控制方案

版本控制方案有两种类型:

  1. 内部版本号:可以在一天内多次递增(例如修订控制号)
  2. 发布版本:这种版本变化不那么频繁(例如语义化版本控制)

人们根据自己的需要使用不同的方案,但语义化版本控制相当广泛地使用,并由GitHub联合创始人Tom Preston-Werner撰写。

语义化版本控制

语义化版本控制遵循X.Y.Z的模式

或者更易读的方式是 [major].[minor].[patch]-[build/beta/rc]

例如:1.2.0-beta

如果软件发生重大变化,如不兼容的API发布,则可以递增major或X

如果引入了向后兼容的API,则递增minor或Y

在修复错误后,递增patch或Z

如何使用Git实现这个版本控制方案?

通过使用标签:

在Git中,标签可用于添加版本号。

git tag -a "v1.5.0-beta" -m "version v1.5.0-beta"

将版本标签v1.5.0-beta添加到您当前的Git存储库中。此后的每个新提交都会通过附加提交编号和提交哈希自动递增标签。可以使用git describe命令查看这些信息。

这里的v1.5.0-beta-1-g0c4f33f中,-1-是提交编号,而0c4f33f是提交哈希的缩写。前缀g代表"git"

可以使用以下命令查看完整细节:

git show v1.5.0-beta


36
请看一下 git describe 命令。该命令展示了最新的标签以及在该标签之后所做的提交数,同时也可能展示存储库的脏数据状态。
正如你所提到的,该命令需要安装 git 并且 .git 文件夹存在,否则无法使用。但是现在几乎所有开发者都会安装 git 和其他工具,这已经成为了常态。请查阅 git describe 以获取更多信息。

7

版本号应该由您自己维护,而不是由git维护。与SVN相反,您没有在每次提交时增加的增量版本号,因此git无法直接确定您的版本。


2
是的。Git名称是从更改派生的哈希值,不代表程序员的意图。这是一个可发布的东西,还是只是一个中途停留?Git无法知道。 - Hack Saw
4
@HackSaw(或其他人在这个晚点的日期)比较的对象是SVN,它也没有提到程序员的“意图”;但是SVN作为集中式版本控制系统可以使用单调递增计数器,而Git则必须退而求其次,采用哈希算法生成唯一标识符。 - SensorSmith

5
  1. 在项目目录(或其他位置)创建名为 build_number 的文件,并将值 1 放入其中。

  2. 进入 git 目录,在 .git/hooks/ 中创建一个名为 "pre-commit" 的文件(不要带有 .sample 后缀)。

  3. 将以下代码放入该文件中。

#!/bin/sh

currentbuildnumber=`cat build_number`
let "currentbuildnumber++"
printf $currentbuildnumber > build_number
currentbranch=`git branch | tr -cd "[:alpha:]"`
git log $currentbranch --pretty=format:"%h - %an, %ar : %s, Build: $currentbuildnumber"

为我工作 :) 享受!


2
这仍然存在与OP所描述的相同问题,如果你有3个人在3个不同的分支上工作,他们可能会得到相同的构建和/或语义版本。 - Lukas Willin
感谢您的回答。请注意,“pre-commit”必须是可执行的。否则,git会打印:“提示:由于未设置为可执行文件,因此忽略了“.git/hooks/pre-commit”挂钩。” - Alexander Lubyagin

4
正如你所说,解决版本问题通常使用分支标签(如语义化版本模式)在git中。
更好的方法是使用git仅跟踪代码库中的更改,忽略(使用.gitignore文件)建立文件并维护一个干净的存储库。
构建结果(预/编译文件,可执行文件,分发文件,zips,exe...)可能取决于环境变量(平台,系统架构等),应该将其分开保存在注册表中。
如果代码库非常大且难以维护,则可以考虑将其分成较小的组件(或git子模块),以避免在开发时出现交叉依赖。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接