244

Starting with v1.11 Go added support for modules. Commands

go mod init <package name>
go build

would generate go.mod and go.sum files that contain all found versions for the package dependencies. If a module does not have any releases, the latest commit of that module is used. If a module does have releases, the latest one is picked as a dependency.

However sometimes I would need functionality that is not in a published release yet, but from a commit made after that release. How do I set go.mod to point not to a release of a module, but to a specific commit in the module's repository? It looks like I can do it by hand in go.mod with

module /my/module
    
require (
    ...
    github.com/someone/some_module v0.0.0-20181121201909-af044c0995fe
    ...
)

where v0.0.0 does not correspond to the last published release tag, 20181121201909 would be a commit timestamp and af044c0995fe would be the commit hash? Should such information to be found and entered by hand, or there is a better way?

Vy Do
  • 46,709
  • 59
  • 215
  • 313
dimus
  • 8,712
  • 10
  • 45
  • 56

6 Answers6

352

Just 'go get' at the commit hash you want:

go get github.com/someone/some_module@af044c0995fe

'go get' will correctly update the dependency files (go.mod, go.sum).

More information: https://github.com/golang/go/wiki/Modules#how-to-upgrade-and-downgrade-dependencies

Everton
  • 12,589
  • 9
  • 47
  • 59
  • 9
    In case getting error "**unknown revision**" or "**invalid version**" - Make sure that you did not specify **hash of PR** (pull request). Even a merged PR might be wrong. Look for the commit hash in the repo under `/commits`, but not under `/pulls`. See more info here: [golang/go#31191](https://github.com/golang/go/issues/31191) explicitly filters out these kind of commits. – Noam Manos Jul 21 '19 at 10:03
  • 8
    the OP askes how to add it to go.mod file , not how to do a `go get` – Nulik Jul 23 '20 at 01:30
  • 11
    @Nulik `go get` is the correct way to update/add-to `go.mod` in the way the OP asked. – Dave C Sep 01 '20 at 16:15
  • 1
    Note that you can also specify a branch or tag name instead of a commit hash. – cambraca Feb 18 '21 at 13:39
  • 2
    @cambraca you cant use the branch name if it's past v1 or you will get `invalid version: go.mod has post-v1 module path` – Ghilteras Oct 04 '21 at 19:29
  • thanks heaps. Cleaning cache and go mod tidy did not help much before that – Nozim Sep 19 '22 at 12:55
180

In addition the answer from Everton on using go get github.com/someone/some_module@af044c0995fe to get a specific commit, you can also use branch names such as:

  • go get github.com/someone/some_module@master
  • go get github.com/someone/some_module@dev_branch

Those examples get the latest commit on the corresponding branch.

It will still be recorded as a pseudo-version in your go.mod file, such as v0.0.0-20171006230638-a6e239ea1c69. (This helps provide a simple total ordering across all versions based on standard semver ordering).

thepudds
  • 4,787
  • 3
  • 20
  • 37
  • 24
    thanks for the pseudo-version explanation. i was trying to do a `replace` to use a temporary fork of some dependency, but could not find a way to make that replacement to point to some commit. Had to create a version tag and specify it like this `replace github.com/original/somelib => github.com/fork/somelib v1.2.3`, which is a bit too much when i just want to quickly test stuff. `replace github.com/original/somelib => github.com/fork/somelib@commithash` and `replace github.com/original/somelib => github.com/fork/somelib commithash` do not work – Zhandos Zhylkaidar Oct 30 '19 at 13:34
  • 6
    1. push your code to `github.com/fork/somelib` @ `dev` branch 2. modify your go.mod file, add a line `replace github.com/original/somelib => github.com/fork/somelib dev` 3. execute `go mod tidy` command. After done these, go will auto replace the `dev` in go.mod to a suitiable pseudo-version. – bwangel Aug 30 '21 at 08:17
  • 1
    you cant use the branch name if it's past v1 or you will get `invalid version: go.mod has post-v1 module path` – Ghilteras Oct 04 '21 at 19:29
  • The @dev_branch doesn't work if the branch name contains slashes. – hookenz Apr 10 '23 at 23:11
34

If you want to temporarily substitute a dependency to a local directory (for example if you work on 2 modules sumultaneously) you can add replace statement at the end of go.mod file:

module example.com/mypkg

go 1.15

require (
  gitlab.com/someone/a_package v0.14.2
)

replace gitlab.com/someone/a_package => ../my_forks/a_package
dimus
  • 8,712
  • 10
  • 45
  • 56
  • The question is asking about latest commit in a remote repo, not a local checked-out state. – SOFe Jun 10 '22 at 06:33
  • 2
    Thank you. I was trying to test a project with a remote module branch because I didn´t know it was possible to target a local directory. – MrMojoRisin Jun 22 '22 at 19:23
29

I have been banging my head for some time that how it works for everyone and I am not able to run it. For me, I had to commit to master branch then only I was able to get it.

For go get to work with specific branch, commit id or tag, you need to enable a flag for go module by running below command

go env -w GO111MODULE=on

after this we will be able to do

go get repo@branchname
go get repo@tag
go get repo@commithash
Chaitanya Gadkari
  • 2,669
  • 4
  • 30
  • 54
22

Also if you put the word latest in place of the tag in the go.mod file it will get changed to the latest tag the modules.

For example:

module /my/module

require (
...
github.com/someone/some_module latest
...
)

will become

module /my/module

require (
...
github.com/someone/some_module v2.0.39
...
)

after running go mod tidy

JFW
  • 585
  • 5
  • 7
11
  • Download source from branch
    go get your-repo@branch-name read output with go module version to be added to require or replace:
    go: downloading github.com/your-repo v1.2.3-0.20210609123456-123123123
  • Later this version can be found as output string of the following command
    go list -m -json your-repo@branch-name | jq '.|"\(.Path) \(.Version)"'
  • If jq is not installed on your PC - manually combine Path and Version values of result from:
    go list -m -json your-repo@branch-name
    separated by space:
    your-repository v1.2.3-0.20210609123456-123123123
Sergey S
  • 889
  • 12
  • 18
  • I got the following error: `malformed module path "foo/bar": missing dot in first path element` for the command: `go list -m -json foo/bar@main` – Dentrax Jun 13 '22 at 07:04
  • @Dentrax Try something like `go list -m -json github.com/foo/bar@main` – spkane Jul 21 '22 at 20:16