hongsy
hongsy

Reputation: 1576

Should I commit vendor directory with go mod?

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

Answers (2)

luben
luben

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

icza
icza

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

Related Questions