If you've adopted a Composer-based Drupal 8 workflow (hopefully using the Drupal Composer/Drupal Project template) where you're keeping dependencies in your project's repository, then you've no-doubt experienced the annoyance of a rogue .git directory ending up in one of your project's dependencies. This will always happen when you're using the -dev version of a Drupal module.
For example, as of the authoring of this Quicktip, the Field Redirection module does not yet have a stable release for Drupal 8. When added to a project using Composer, the results look like this:
Michaels-MacBook-Pro:dcoweek5 michael$ ddev composer require drupal/field_redirection
Executing [composer require drupal/field_redirection] at the project root (/var/www/html in the container, /Users/michael/sites/dcoweek5 on the host)
Using version 2.x-dev for drupal/field_redirection
./composer.json has been updated > DrupalProject\composer\ScriptHandler::checkComposerVersion
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing drupal/field_redirection (dev-2.x e1c30f2): Cloning e1c30f24f9 from cache
Writing lock file
Notice on the "Installing drupal/field_redirection..." line, it indicates that the project is cloned, not downloaded. This means that a .git directory has been created in the Field Redirection directory.
Note that I'm calling Composer as "ddev composer ..." - this is because I use DDEV as my local development environment and am utilizing its built-in Composer command.
If this goes unnoticed, and you attempt to do a normal "git add/commit" workflow for the new module, you'll end up with a somewhat-friendly Git message indicating that you now have a Git submodule.
Unfortunately, Git submodules aren't normally necessary nor wanted when you are committing dependencies to the project repository. So, the typical solution is to delete the .git directory of the dependency prior to performing the "git add/commit".
Luckily, there's an easier way! Travis Neilans recently pointed me in the direction of the Composer Cleanup VCS Directories project. By adding this as a dependency of your project, any .git directories that result from adding project dependencies will be automatically removed! First, install the Composer Cleanup VCS Directories project using:
composer require topfloor/composer-cleanup-vcs-dirs
Then, anytime you use "composer require" to install a project dependency, if there's a .git directory, you'll see a message indicating that it has been automatically removed.
Deleting .git directory from /var/www/html/web/modules/contrib/field_redirection/.git
Comments
This is great but creates a follow-up problem
Thanks a lot for this tip, exactly what I was looking for. However, when those .git directories got deleted, the next time this module should be updated, the composer process stops with the message "Update failed (The .git directory is missing". I can confirm that I want to reinstall and all is like before.
To avoid this message I tried the option "--no-interaction" but that simply stops the process and doesn't install anything.
Any idea if any other command line option would prevent that from happening?
That's a good point. When it…
That's a good point. When it comes time to update the dependency, I normally remove then re-require.
Sure, but that very…
Sure, but that very inconvenient and it is not possible during deployment or automated testing. I guess the idea is nice but I have to remove that from my tool chain again - unless composer had an option to ignore missing .git directories simply.
Another way to do the same thing
Here's another way to do the same thing that doesn't involve adding a new dependency. You can add a line (first one below) to the "scripts" section of the composer.json:
"scripts": {
"remove-git-submodules" : "find . -mindepth 2 -type d -name .git | xargs rm -rf",
"pre-install-cmd": [
"DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
],
"pre-update-cmd": [
"DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
],
"post-install-cmd": [
"DrupalProject\\composer\\ScriptHandler::createRequiredFiles",
"@remove-git-submodules"
],
"post-update-cmd": [
"DrupalProject\\composer\\ScriptHandler::createRequiredFiles",
"@remove-git-submodules"
]
},
Good tip for that scenario,…
Good tip for that scenario, but I'd add a note about committing dependencies to your repository is bad practice.
Don't commit modules to the repository in the first place
Just to add more information to the previous comment, the only thing that needs to be committed when adding a new module is the new line in
composer.json
(and possibly changes made to the lock file after a rebuild).The whole point of using Composer is that it manages dependencies for you. You don't need to commit them, and you can avoid this whole problem with submodules altogether. When you deploy, you run a
composer install
command, which builds everything needed.
Agreed, we never commit…
Agreed, we never commit dependencies ourselves. But still the .git directories in sub-directories can get into your way: one sample is PhpStorm which wants to manage those repositories when available and I have to disable them each and every time a new one gets recognised. Another example is caching in CI/CD with GitLab where you could easily tell that all untracked files should be cached but that's ignoring those that come with .git directories themselves.
Both scenarios might be bugs or glitches with those other tools but I can also imagine when I why their current behavior could make sense in other contexts.
I disagree. Not committing…
I disagree. Not committing Composer dependencies just exchanges problems like this with different problems. Both are valid approaches.
nope
Build workflows are not the only game in town.
Git workflows are simple, still work well, and fit the majority of small development needs. The development snobbery around the whole build vs git workflow thing is really quite unfortunate.
No, I'm not going to stand up learn an entire chain of build tools for a simple one developer website development workflow just because a bunch of enterprise and big shop developers decided it was 'best practice'.
And composer doesn't belong on a production site.
The Git workflow still works well for plenty of use cases.
Ideally there should be a simple way to tell the parent repo to simply ignore and .git folders in subdirectories.