Skip to content

Instantly share code, notes, and snippets.

@kneerunjun
Last active January 3, 2023 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kneerunjun/8f0c6e2d419eac1123f233a40262d820 to your computer and use it in GitHub Desktop.
Save kneerunjun/8f0c6e2d419eac1123f233a40262d820 to your computer and use it in GitHub Desktop.

go get any intended version


Whilst writing your own GO libraries, we GoPhers have a sound understanding of the packages and GO modules. but somehow when making our own libraries we tend to miss out on a small detail that can limit your versioning on git. I have put this up just so that you can benefit from my experience / exploration of solutions on the internet.

Lets see the problem first hand and then I bring out the solution/tweak.

We are writing this small uni-file library (for brevity sake Im assuming we have this small library)

go mod init github.com/kneerunjun/mylog
module github.com/kneerunjun/mylog

go 1.15

require (
	....
)
package mylog

import(
 log "github.com/sirupsen/logrus"
)

func Setup(){
// simple steps to setup the logging configuration
}

Lets tag the versions so as to provide a +ve interface for the consumers of our library

git tag -a "v0.0.0" -m "inital development"
git push origin --tags

Now you are free to move ahead with the development on the master branch while the client / consumer of this library can stay on a pinned version. Even if the master branch has breaking changes, it would not affect the client since its pointing to a stable version.

Now when referencing this library from some other project this what we do

package main 
import(
 "github.com/kneerunjun/mylog"
)
func main (){
	mylog.Setup()
}
module github.com/kneerunjun/myproject

go 1.15

require (
	github.com/kneerunjun/mylog v0.0.0
)

Notice how the client library is pointing to at the specific version

Meanwhile lets assume the master branch has advanced to a new change and the signature of the Setup function has changed.

package mylog

import(
 log "github.com/sirupsen/logrus"
)

func Setup(f *os.File){
// simple steps to setup the logging configuration
}
git add. 
git commit -m "Setup changed, now takes a file for logging"
git push origin master

After enough testing, and satisfactory results in unit testing

#Im aware this is not a platform change, and the ideal version should have been v0.1.0 and not v1.0.0
git tag -a "v1.0.0" -m "enhancement"
git push origin --tags

Its now time for myproject to upgrade to this version if it requires logging to a file

go get -u github.com/kneerunjun/mylog@upgrade=v1.0.0

Boom! now your project has the latest version onboard

package main 
import(
 "github.com/kneerunjun/mylog"
)
func main (){
	f := os.Open("")
	mylog.Setup(f)
}
module github.com/kneerunjun/myproject

go 1.15

require (
	github.com/kneerunjun/mylog v1.0.0
)

Just when everything is seemingly well we land up in the issue if we go ahead of version v2.0.0 - you may ask if migrating from v0.0.0 to v1.0.0 wasnt a problem whats so wrong with v2.0.0 ?

We make changes to mylog considering that this is a major change, the leading digit in the version number changes.

package mylog

import(
 log "github.com/sirupsen/logrus"
)
func ErrLog() {
}
func Setup(f *os.File){
// simple steps to setup the logging configuration
}
git add. 
git commit -m "added more logging features for error"
git push origin master
git tag -a "v2.0.0" -m "Error loggin feature"
git push origin --tags

Here lets have a look at the versioning system, the way GO looks at it. Back in myproject

go get -u github.com/kneerunjun/mylog@upgrade=v2.0.0
 
invalid version: module contains a go.mod file, so major version must be compatible:

But very surprisingly if I try this:

go get -u github.com/kneerunjun/mylog@master

It does go to the master branch and get the bleeding edge code! but labels the same as indirect in require section. This appears as only a hack and is crude way of pointing to the lastest on the master branch. Incase the master branch has been not merged into, will mean the entire dependency is broken. There has to be a way where I can go get-u from irrespective of the branch.

The way Go sees it v<Platform changes>.<Major changes>.<Minor changes> is how the version should be annonated. Implies when pointing to a version that was intended to be developed on a different platform and such has to be explicity appearing in the go get path.

Hence the go get command should have been like this

go get -u github.com/kneerunjun/mylog/v2

Hence all the versions uptil v0.x.x to v1.x.x can work implicitly.

If you now observe this, there is no go module at the locaiton github.com/kneerunjun/mylog/v2 and such will work only when you make the change in the mod name.

Back in mylog project

module github.com/kneerunjun/mylog/v2

go 1.15

require (
	....
)

Re-tag it

git add . 
git commit -m "altering module name"
git push origin master
git tag -a v2.0.1 -m "resolving tagging for go mod"
git push origin --tags

You now can use intended version from the git tagging in myproj

go get -u github.com/kneerunjun/mylog/v2@v2.0.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment