Go: 如何将Git版本添加到构建的二进制文件中?

6
我想将当前的git修订版本号添加到由go build构建的二进制文件中,以便我可以执行./mybinary --revision来查看它是从哪个版本构建的(通常用于部署后的故障排除)。
显然,我不能将修订号放入源代码中,因为这会用新的修订号更改源代码。
我想知道是否有其他方法可以做到这一点?或者您认为这只是一个坏主意?如果是这样,建议建立已构建二进制文件与其源代码版本之间的关系的方法是什么? 在分布式版本控制系统中,版本号似乎不是一个好主意。

那是一个懒惰的回答,@LazyBadger。你真正地荣耀了你的名字。 - vonbrand
5个回答

10

如果您可以将git版本号放入$VERSION中,并在主包中有一个名为version(类型为字符串)的变量,您可以在构建过程中使用以下命令设置它:


如果您能够将 git 的修订版本放入 $VERSION 中,并且主要包中有一个名为 version (字符串类型) 的变量,您可以在构建过程中设置它:
#!/bin/sh
VERSION=`git rev-parse --short HEAD`
go build -ldflags "-X main.version=$VERSION"  myfile.go

这真是太棒了。顺便说一下,git describe 做了很多好事情(特别是如果你有标签)。 - Dustin
构建时出现错误 - -X标志需要形式为importpath.name=value的参数。 - Vivek R
@VivekR 感谢您的评论,我已经修正了我的答案。 - topskip

6
从Go 1.18(2021年第四季度/2022年第一季度)开始,正常流程不再涉及任何ldflags
请查看issue 37475CL 356013

go命令现在将版本控制信息嵌入二进制文件中,包括当前检出的修订版本和一个指示是否存在已编辑或未跟踪文件的标志。

如果在Git或Mercurial存储库内的目录中调用go命令,并且main包及其包含的main模块在同一存储库中,则会嵌入版本控制信息。
使用-buildvcs=false标志可以省略此信息。

此外,go命令还嵌入有关以下信息:

  • 构建包括构建和工具标记(使用-tags设置),
  • 编译器,
  • 汇编器和
  • 链接器标志(如-gcflags),
  • 是否启用了cgo以及如果启用了,则cgo环境变量的值(如CGO_CFLAGS)。

使用-buildinfo=false标志可以省略此信息。

可以使用以下命令一起读取VCS和构建信息:

  • go version -m file
  • runtime/debug.ReadBuildInfo(对于当前运行的二进制文件)或
  • 新的debug/buildinfo
CL 373875添加了:
  • BuildInfo结构具有关于如何构建二进制文件的其他信息的新字段。
  • 新的GoVersion字段保存用于构建二进制文件的Go版本。
  • 新的Settings字段是BuildSettings结构的切片,保存描述构建的键/值对。

2

我会创建一个名为version.go的文件,其中只包含一个var version string变量,并在调用go build之前处理它,然后在处理完成后将其重置。换句话说,Go语言不支持任何类型的代码生成,因此您需要依赖于外部工具来完成此操作。


这对通过git标签处理语义化版本控制非常有用。修改version.go的一种选项是使用sed:sed -i 's/var Version = .*/var Version = "'$(git describe --always)'"/' path/to/version.go - J. Pelaez

1
对于在Git中进行版本控制的所有代码,获取任何变更集的标识字符串的最明显方法(在我留给您的任务中将此字符串显示在“--revision”选项上)是:
  • 至少偶尔使用标签
  • 在构建阶段使用git describe(使用相关选项)

0

通常你会使用标签(在其他版本控制系统中也称为标签)来标记构成特定版本的文件。 http://git-scm.com/book/en/Git-Basics-Tagging。 我通常会创建包含版本和构建日期的标签,例如v1.2_29Mar2013。如果我有几个产品可以从同一代码库构建,我会包括一些用于识别产品的内容。


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