Go Module Versions From Git Log
One of the more elegant design decisions the new Go Modules introduced is backwards compatibility with packages that don’t yet use semantic versioning by specifying a special version that includes a Git reference:
require mellium.im/cli v0.0.0-20180802-f77b0b28dc2b
The v0.0.0
makes it compatible with semantic versioning and ensures that if
the package starts tagging their versions in the future, all versions are an
upgrade over the special case.
Meanwhile, the date makes sure that commits are sorted correctly (newer commits
are higher “versions”).
Finally, the commit or other reference lets the Go tool actually fetch the
package from the repo just like it would have before modules were introduced
(except now you can easily get a commit other than HEAD on the default branch).
All of this is great, but there’s just one problem: actually getting that
version string is a pain in the ass.
To be clear, any date works so you can always just write out the current date to
make it sort correctly, and the number of digits in the hash isn’t important so
normal short hashes or full hashes would work, but it still frustrates me when
things aren’t consistent and I’d like to be able to reference the commit date
and know about how old my dependencies are at a glance.
To fix this, you can make Git spit out the version for you any time you run git log
, just add the following to your ~/.gitconfig
file (or to /etc/gitconfig
to make a sytsem wide change, or .git/config
in your repo if you want to
change the format only for a specific repo):
[core]
abbrev = 12
[format]
pretty = %Cred%cd-%h%Creset %C(blue)%aN%Creset %C(yellow)%d%Creset %s %Cgreen(%cr)%Creset%+N
[log]
abbrevCommit = true
decorate = short
date = "format:%G%m%d%H%M%S"
The value of pretty
is just my personal preference, your mileage may vary,
but the important part is the %cd-%h
which spits out the commit date and
hash, eg. 20180810141753-f6c9684b8d02
.
You can change the date format by modifying log.date
or the number of nibbles
in the commit hash by modifying core.abbrev
.
This results in log lines like the following (from my mellium.im/xmlstream
package, with color elided):
20180821111446-8253112fd962 Sam Whited (HEAD -> master, tag: v0.13.1, origin/master, origin/HEAD, freenas/master) xmlstream: add single token reader (5 weeks ago)
20180820234553-5186e1aeef84 Sam Whited (tag: v0.13.0) xmlstream: remove Flush from TokenWriter (5 weeks ago)
20180818115214-acd593680ab3 Sam Whited ci: test againsnt Go 1.11 RC1 (5 weeks ago)
20180818114938-d9dd79c0cfd2 Sam Whited (tag: v0.12.3) xmlstream: add a TokenReadCloser interface (5 weeks ago)
20180810141753-f6c9684b8d02 Sam Whited (tag: v0.12.2) ci: bump to Go 1.11 Beta 3 (6 weeks ago)
20180810141617-02c5add58b48 Sam Whited xmlstream: add TeeReader (6 weeks ago)
20180802120635-4a6214452a60 Sam Whited ci: don't test with -race (which fails on muscl) (8 weeks ago)
20180802120514-e9570575e36a Sam Whited ci: add missing dep (git) (8 weeks ago)
20180802120414-cbe02477b431 Sam Whited xmlstream: remove dep support (8 weeks ago)
Updates
2019–01–24
I should also point out that this can be accomplished with command line flags as well as by modifying the config file. This is useful when automating package building, among other things:
git show --abbrev-commit --abbrev=12 --date='format:%G%m%d%H%M%S' \
--pretty=format:v0.0.0_%cd_%h --no-patch HEAD
The Git logo was created by Jason Long and remixed under the terms of the Creative Commons Attribution 3.0 Unported license. The Go logo is copyright the Go Authors.