Using Composer Without GitIgnoring Vendor/
composer install
, it’s probably mostly almost safe” criticism, but actually it’s quite tricky to run Composer without excluding vendor/
from source control so I thought I’d share how we did it so that anyone who wants to do so can learn from my experience!The Prescribed Method
Let’s start with the usual method of using composer:
- Create
composer.json
to describe the dependencies - Run
composer update
to find specific versions of those dependencies and write exact versions tocomposer.lock
. Repeat this step ifcomposer.json
changes. - Add the
vendor
directory to.gitignore
, but add thecomposer.*
files. - Run
composer install
on all platforms (and do this again whenevercomposer.lock
changes.
That’s the basic composer pattern, and it works well. Most people should do it this way.
Checking Libraries into Git
There are a few reasons you might want to check your dependencies into source control yet still use composer, such as:
- Either your users or your tools aren’t ready to start using composer yet
- Your live servers don’t have internet access so dependencies need to be packaged with code
- Running composer on live scares you because it’s recently had some bad security press
- You like composer for managing dependencies, or think it will become production-ready soon, but you’re not running it on live yet – because you, your sysadmins or your IT director aren’t ready
When I tried to just commit my vendor directory, some git submodule weirdness ensued, and in fact, the documentation does cover this:
Adding dependencies installed via git to a git repo will show them as submodules. This is problematic because they are not real submodules, and you will run into issues.
I did, indeed, run into issues.
The workaround (from the same docs) is to add a .gitignore
line that removes all .git
directories within your vendor directory. So add this line to the .gitignore
file at the same level as composer.json
and vendor/
:
vendor/.git
Now when you install dependencies into composer (I found I had to git rm
my entire vendor
directory, commit, and then composer install
again to clean up my earlier mistakes) you can safely add the vendor directory to the project and treat it as a library directory you had unzipped downloaded packages to. Apart from it’s fabulous autoloader and easy-to-update format, that is :)
One alternative might be to use composer for dev, release build and all other environments that are under your control.
Then on the live systems you have a complete set of files/code to deploy.
I’ve been working with this and it is a great compromise. It allows to use composer the way it is meant to and still you end up with a release (archive, rpm, etc) that has no further external dependencies.
I’ve been leaning on this direction too.
Prepare the release locally (or in Continuous Deployment server), build all the assets needed, installing all composer packages, checking git modules if any. Then just rsync the release to production.
It also removes the need of having GIT and private keys (eg: when having private composer packages) on the server. One less key to manage.
+1 for this.
I use this approach at work. I build on a separate local server and rsync to production (This is OK if you do not have to deploy to multiple servers.). I use a fabric script for automating that process and give a really simple way to anyone to easily update/deploy to staging/release.
I use the symlinc switch trick found on this blog in that fabric script :)
We use this method too. A build script on our server runs composer to “package” our app and all its parts. (a folder)
Then it sends the whole thing to production. With this setup, composer doesn’t need to be installed or run on production.
Excellent post! I’m thinking of using the same technique for some projects where I can’t control the deployment process and the service just pulls from the source repository.
In many cases, running the composer install, update, or require commands with the –prefer-dist option will download the package’s source from the preferred distribution package (usually a zip file, if it’s a standard package hosted on GitHub). This distribution package does not include the .git folder. This method works well for stable packages with tagged releases.
The opposite of this option is –prefer-source, which downloads the package source straight from the repository.
There are obviously caveats to using both of these options, for packages that do not follow the standard patterns, so the best bet is to go with your recommendation of adding vendor/.git.
would be great to link specifically to the bad press on composer security, interesting post but not sure yet
I’ve been doing –prefer-dist for months now and was really excited about just adding vendor/.git so I didn’t have to think about it anymore. Unfortunately, it doesn’t seem to work for me, as its still seeing the .git directories and creating submodules. (And yes, I did commit the .gitignore file update first and separately.)
Any ideas?
This is a useful technique, and I use the following .gitignore; maybe it’s helpful:
/vendor/**/.git/
None of the mentioned .gitignore statements actually seem to work (not the one in the article nor then ones in the comments). Is it possible that you installed only packages with tags and have the prefer-dist flag on so there are no .git folders in the first place?
My starting point is a project that has vendor/ in gitignore. So nothing in the vendor folder is originally under version control.
Changing
[code]vendor/[/code]
to
[code]vendor/.git[/code]
or even
[code]vendor/**/.git/[/code]
and then doing a
[code]git add . –all[/code]
adds dependencies with a .git folder as submodules.
Me too, here is my solution:
https://stackoverflow.com/questions/27726794/php-composer-git-gitignore-and-one-step-install/27727171#27727171
Thanks a lot for this tip!
Implemented it in the projects at work and now people don’t need to always keep updating composer, specially because of the api limits.
Pingback: Using Composer Without GitIgnoring Vendor | Laravel News
I was also thinking of putting the vendor directory under git control because I want to avoid having to install dependencies using ‘composer install’ in the course of deployment to test and prod stages. But isn’t this causing an issue with platform/OS dependent content in the vendor directory? How far can the vendor directories of the same project (same state of composer.lock) differ depending on Windows, Mac, Linux as the underlying OS? I think the vendor/bin content differs between Windows and Mac as far as I can see.
Asking this same question on stack overflow got some downvotes. Guess people really don’t want you to do this.
My main reason was because I don’t want at extra requirement, shell access, for users.
https://stackoverflow.com/questions/27726794/php-composer-git-gitignore-and-one-step-install
I recommend to use this method.
Edit composer.json and add this line.
“config”: {
“preferred-install”: “dist”
}
Remove all folder in vendor and run composer install. Folder .git should not appear in vendor folder anymore.
I have found this to be the most reliable method. It is possible that not all packages downloaded by composer will end up in the vendor directory. Particularly for CakePHP, many packages are actually plugins and will get moved to the Plugins directory.
Thanks for the tip on adding that to composer, that is what did the trick for me, works well.
It really works! Thanks!
How about following idea?:
– We keep a separate repository for project dependencies only
but that repository contains only composer.json and composer.lock.
– We maintain that repository on each environment like dev, staging, production
– In project repository, we have vendor directory which has a soft link to
vendor directory of dependency repository’s vendor directory.
– On dev, we do composer update on dependency repository,
test everything and if works fine then commit composer.json and composer.lock
– On Staging, Production, we only do composer install
but only when we did composer update on Dev last time
otherwise we don’t do anything with dependency repository on each environment.
Circling back to add that today I’d add `composer.json` and `composer.lock` to git and gitignore `vendor/` – Composer is a much more stable tool than it used to be!