如何在 Git 中管理版本号?

Posted

技术标签:

【中文标题】如何在 Git 中管理版本号?【英文标题】:How to manage the version number in Git? 【发布时间】:2016-10-15 07:41:06 【问题描述】:

让我们想象在git 上维护的blerp 命令行工具。这个工具有一个(隐藏的)--version 选项,它返回它的version(比如说0.1.2)和另一个--commit,它返回构建它的提交号。

版本和提交号都硬编码在代码库中。

现在我做了一个错误修复,然后提交并重建我的程序。我仍然会看到0.1.2,尽管这个新版本与原来的 0.1.2 不同。只有提交会告诉我它与 0.1.2 不同。该错误修复是否值得使用不同的版本号?

一种解决方案是,每次提交时,我都会增加硬编码的版本号(这意味着每次提交时始终修改至少 2 个文件)。这是一个绑定解决方案,当开发人员在不同的活动分支上工作时它不起作用。如果 Bob 使用 0.1.2 版本的功能 foo,而 Alice 使用同一版本的 bar 功能。他们如何增加版本号? Bob 可以使用奇数,Alice 可以使用偶数。如果 Eve 开发第三个功能怎么办?

另一种解决方案是使用 Git 标签自动生成版本号。脚本可以找到最近的以v 开头的标签,例如v0.1.2,并使用标签名称作为版本号加上当前提交的前n 位数字(v0.1.2 (build 4acd21))。如果工作目录是干净的,这很有效。可以想象在内部版本号前添加* 表示工作目录不干净。此解决方案的主要问题是,如果有人导出源,它将无法构建 blerp

有什么可能的替代方案可以解决这个问题?

【问题讨论】:

通常,您应该避免将版本放入源文件。理想情况下,您将有一个将版本编码为内部版本号的构建过程。这样,版本就与用于构建它的源代码无关。然后,该过程还可以在某处对提交 id 进行编码,因此您始终知道构建源的来源。至于存储版本号,常见的解决方案是使用标签。这也为您带来了好处,您可以通过查看标签轻松地按版本浏览存储库中的版本。 @poke 如果您只是从 SCM 获得源,您如何获得产品中的版本号。 blerp 的版本是什么? 通常,您发布的内容与版本控制中的内容不完全相同。因此,您可以按照我的描述在构建过程中应用该版本。 我知道这是一个老问题,但我制作了一个脚本来执行一些版本管理 + 更多功能:github.com/jv-k/bump-version.sh 【参考方案1】:

Alexey Kiselev 和 Dario 已经暗示了答案,但我会尝试详细解释。

版本控制方案

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

    内部版本号:可以在一天内多次递增(例如修订控制号) 已发布版本:更改频率较低(例如语义版本控制)

人们根据需要使用different schemes,但semantic versioning 被广泛使用并由 GitHub 的联合创始人 Tom Preston-Werner 撰写。

语义版本控制

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

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

例如1.2.0-beta

major or X 可以在软件发生重大变化时递增,例如向后不兼容的 API 版本。

如果引入向后兼容的 API,minor or Y 会递增。

patch or 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

【讨论】:

【参考方案2】:

请查看git describe 命令。此命令向您显示最新标签和设置标签后提交的数量。还可以显示存储库的肮脏程度。

正如您提到的,如果没有安装 git 存储库(.git 文件夹)和 git,此命令将无法运行。但是今天几乎无法想象没有 git 但安装了所有其他工具的开发人员。

【讨论】:

【参考方案3】:

修订号应该由您维护,而不是由 git。与 SVN 不同,您不会在每次提交时增加修订号,因此 git 无法开箱即用地对您的版本进行上下文化。

【讨论】:

是的。 git 名称是从更改派生的哈希值,不涉及编码者意图。这是一个可以释放的东西,还是只是在路上停下来? Git 不知道。 @HackSaw(或其他迟到的人)比较的是 SVN,它也没有提及编码器的 意图;但是集中的 SVN 可以使用单调递增的计数器,而 Git 必须依靠散列来生成唯一的 id。【参考方案4】:

正如你所说,版本控制问题通常在 git 中使用 branchtags 解决(如 semantic versioning 模式)。

更好的方法是使用git 仅跟踪代码库中的更改,忽略(使用.gitignore 文件)构建文件并维护干净的存储库。

构建结果(预编译/编译文件、可执行文件、分发文件、zip、exe...)可能取决于环境变量(平台、系统架构等),应单独保存在注册表。

如果代码库非常大且难以维护,也许您应该考虑将其划分为更小的组件(或git submodule)以避免在开发时出现交叉依赖。

【讨论】:

【参考方案5】:

    在项目目录(或您想要的位置)build_number 中创建文件并将其值 1 放入此文件中

    转到 git 目录并在 .git/hooks/ 中创建名为“pre-commit”的文件(不带 .sample)

    把这段代码放在那里

#!/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,构建:$currentbuildnumber"

为我工作:) 享受吧!

【讨论】:

以上是关于如何在 Git 中管理版本号?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# windows 服务中使用 Git 标签号代替 SVN 版本号

如何获取 Git 内部版本号并将其嵌入文件中?

如何管理在每个 git 版本中添加私有代码片段?

如何在git中管理版本文件

GIT如何拉取主版本中的最新代码到自己空间的分支

GIT如何拉取主版本中的最新代码到自己空间的分支?