Commit your Composer-managed files to version control

According to the Composer documentation, you shouldn't commit to version control any of the files in packages that are managed by Composer. For a Drupal project, that means the following folders are not in your git repository:

  • vendor
  • web/core
  • web/modules/contrib

Bluntly, I think this is the wrong thing to do. Doing the exact opposite saves you time, effort, heartache, and energy.

Let's start by comparing the two workflows.

Composer-recommended workflow: the wrong way

  1. Alice, the developer, updates some packages in her local dev.
  2. She commits only the composer.json and composer.lock files.
  3. Bob pulls changes, and runs composer install to update his local dev.
  4. When the project is deployed, the server needs to run composer install as part of the deployment process.

Git-managed workflow: the right way

  1. Alice, the developer, updates some packages in her local dev.
  2. She commits all the new and changed files.
  3. Bob pulls changes.
  4. When the project is deployed... it's deployed. All the files necessary to run the app are in git, and so updating the server's git clone gives it all the files.

The first reason this workflow is better should jump out: developers save time. Git is much faster and pulling files from a repository than Composer is at resolving, downloading, and installing packages. Switching git branches is fast, even when a lot of files change. Having to run Composer because one branch has package updates on it and the other doesn't, or has different ones, is a waste of developer time.

The second reason is related: save time in deployment. That's not just developer time, that's time your production server is down.

The third reason is more philosophical: Composer is not a file management tool. It's a dependency management tool. Let Composer do what it does well, which is figuring out which versions of which packages should be installed. Let git handle what it does well, which is synchronizing different copies of a codebase. Purists may point out that git is a version control tool, not a file management tool: that's a valid point, but doesn't diminish my argument: commit all files, and then use rsync or whatever to get the files from a git clone to the server.

Related to this: don't make your webserver do package management work; that's not its job. And don't make Bob repeat the work Alice already did.

Finally, committing files to git puts them under version control. That's merely stating the obvious, but putting files under version control has many benefits.

  • IDEs typically ignore git-ignored files for things like searching and code analysis. On my IDE at least (VSCode), disabling that means it then wants to include things like the uploaded files folder.

  • Similarly, search tools such as ag and ack take .gitignore files into account, and having to override that robs you of useful behaviour.

  • Finally, files under version control are easier to debug and tinker with. I for one often go digging in core or contrib modules, trying to figure out why something isn't working the way it's supposed to, or trying to fix a bug. To do that, I put in dump statements; sometimes tons of dump statements. (I can never get xdebug to work. Dump statements are quick and easy.) With code under version control, cleaning up all that mess is trivial: git can discard all changes. Without version control, I'm hunting through files for all the debug changes I made, or bouncing on CMD-Z like it's still the dark ages.

So, put all your files in version control. And remember the adage: if it's not under version control, it doesn't exist.