Should we commit
vendor in our Go projects?
Since the introduction of Go modules, the prevalent
opinion on the internet is that we should NOT commit
the vendor directory of our projects.
The argument against committing vendor is that it’s
unnecessary, because the Go tools can resolve and find
dependencies when needed on-the-fly. All public Go modules are
also hosted by various Go Proxy servers for redundancy.
While I agree that it’s technically
unnecessary and bloats the repo, I’d like to give some
arguments in favour of committing
Here is a list of arguments for committing vendor:
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.
Not in your repo, not your code.
We may use 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 and nothing breaks unexpectedly.
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.
Committing vendor can improve your code review process.
Typically, I’m used to committing dependency changes in a
separate commit, so they can be easily viewed if the reviewer
Here’s an interesting observation related to bloating the repo.
If I make code review, and a team member has included a new
dependency with 300 files (or updated one with 300 files
changed), I would be pretty curious to deep dive into that
and start a discussion about the code quality, the need for
this change or alternative Go modules. This may lead us to
actually decrease our binary size and overall complexity.
If I just see a single new line in go.mod in new MR, chances
are I won’t even think about it.
CI/CD jobs which perform compilation and build steps need
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)
As a pseudo argument I can ask why important open source
Go projects like Kubernetes
are committing vendor, if it’s not necessary?
For my own peace of mind I would always prefer to commit the
vendor directory alongside go.mod and go.sum
while at the same time try to keep the project dependencies
vendor directory SHOULD NOT be committed for Go
libraries, frameworks or code which doesn’t produce
executable binaries, unless you have a really good
reason to do it.