2025-04-20 Build Info In Go Binaries

I like having assorted build info in my Go binaries and here’s how I do it.

At the core: Go linker flags, specifically -X importpath.name=value - “Set the value of the string variable in importpath named name to value.”

Other methods exist but this is the right combination of powerful, resilient, and clear for me.

This lets me do this in my code:

var GIT_VERSION string
var GIT_BRANCH string
var BUILT_AT string

And then this at build time (taken from my Makefile, hence the $$):

-ldflags "-X 'main.GIT_VERSION=$$(./git-version)' -X 'main.BUILT_AT=$$(date)' -X 'main.GIT_BRANCH=$$(git symbolic-ref --short HEAD)'"`

That gives me:

  • BUILT_AT which is just the build timestamp - useful to make sure I’ve not missed restarting a service to pick up changes etc.

  • GIT_BRANCH which is, unsurprisingly, the name of the branch - useful to see if I’m running on a main build, or something from a feature branch

  • GIT_VERSION which is the output of a short script that gives me a slightly more detailed idea of what I built from

git-version is:

#!/bin/bash

HEAD_HASH=$(git rev-list -1 HEAD)

GITVERSION=$HEAD_HASH

# https://stackoverflow.com/a/2659808
DIRTY=$(git diff-index --quiet HEAD -- || echo '-DIRTY')

GITVERSION+=$DIRTY

echo "$GITVERSION"

which outputs the commit hash as a string, plus a -DIRTY suffix if there are uncommitted changes - useful to know exactly what I built from, and/or if there was anything funky - e.g.:

$ ./git-version
ace0fba5eace0fba5eace0fba5eace0fba5e-DIRTY

Then I can simply use those as needed, e.g. for dumping information when running with --version:

$ ./mybin --version
GIT_VERSION: ace0fba5eace0fba5eace0fba5eace0fba5e-DIRTY
GIT_BRANCH: feature/foo
BUILT_AT: Mon 30 Feb 1712 03:13:37 CEST

I don’t write a huge amount of Go, so it wouldn’t surprise me to learn that there are better ways / room for improvement, but this works nicely for me!