Reputation: 1576
I am using go modules on go1.12 to handle my Go dependencies. Is it best practice to also commit the vendor/
directory into version control?
This is somewhat related to Is it best-practice to commit the `vendor` directory? which asks this question in the case of using dep
. With dep
, commiting vendor/
is the only way to get truly reproducible builds. What about for go modules?
Upvotes: 9
Views: 11818
Reputation: 2712
I'd like to give some arguments in favour of committing vendor
, go.mod
and go.sum
.
I agree with the accepted answer's arguments that it's technically unnecessary and bloats the repo.
But here is a list of pro-arguments:
Building the project doesn't depend on some code being available on Github/Gitlab/... or the Go proxy servers. Open source projects may disappear because of censorship, authors incentives, licensing changes or some other reasons I can't currently think of, which did happen on npm, the JavaScript package manager, and broke many projects. Not in your repo, not your code.
We may have used internal or 3rd party Go modules (private) which may also disappear or become inaccessible, but if they are committed in vendor, they are part of our project. Nothing breaks unexpectedly.
Private Go modules may not follow semantic versioning, which means the Go tools will rely on the latest commit hash when fetching them on-the-fly. Repo history may be rewritten (e.g. rebase) and you, a colleague or your CI job may end up with different code for the dependencies they use.
CI/CD jobs which perform compilation and build steps will not waste time and network to download the dependencies every time the CI job is executed. All needed dependencies are local and present (go build -mod vendor
)
Setting up CI/CD jobs authentication for downloading private Go modules is not necessary (simpler).
Go dependencies almost always are text files (source code) and it's very cheap to store them in the repo. Not the case for every other language.
Committing vendor may sometimes improve the code review process. Typically we always commit dependency changes in a separate commit, so they can be easily viewed if you're curious.
Here's an interesting observation related to bloating the repo. If someone makes a code review and a team member has included a new dependency with 300 files (or updated one with 300 files changed), it may be interesting to look inside and eventually start a discussion about alternatives/quality if needed. This may lead to actually decrease your binary size and overall complexity.
If there is just a single new line in go.mod
in a new Merge Request, chances are we won't even think about it.
When committing vendor is wrong?
vendor
should never be committed when the project is a Go library (imagine you make the new gorilla/mux). Only for projects that produce executable binaries.
Upvotes: 25
Reputation: 417767
Unless you need to modify the vendored packages, you shouldn't. Go modules already gives you reproducible builds as the go.mod
file records the exact versions and commit hashes of your dependencies, which the go
tool will respect and follow.
The vendor
directory can be recreated by running the go mod vendor
command, and it's even ignored by default by go build
unless you ask it to use it with the -mod=vendor
flag.
Read more details:
Go wiki: How do I use vendoring with modules? Is vendoring going away?
Command go: Modules and vendoring
Command go: Make vendored copies of dependencies
Upvotes: 13