Tricks for using Composer in local development

Last updated on
17 October 2025

When you are developing or maintaining a contrib project, you may find that the process of modifying code, pushing changes to Drupal.org, and then having Composer update your local environment to pull down what you pushed is tedious and time-consuming. In addition, Drupal.org does not allow history to be rewritten, but if you are developing something experimental you might not want to make your changes final until you've had a chance to test them.

Wouldn’t it be great if you could have Composer check out your local copy or issue fork of a contrib project instead of using the official version? You can if you add a repository to your site’s composer.json! Here’s how:

  1. Open the composer.json file for your test site (not for the contrib project) and modify the repositories section as follows.
    • To symlink a local folder that has a composer.json file:
          "repositories": [
              {
                  "type": "path",
                  "url": "path/to/your/local/copy"
              },
              {
                  "type": "composer",
                  "url": "https://packages.drupal.org/8"
              }
          ],
      
    • To clone a local folder or issue fork that has a composer.json file:
          "repositories": [
              {
                  "type": "vcs",
                  "url": "git@git.drupalcode.org:issue/your_project_name-0000000.git"
              },
              {
                  "type": "composer",
                  "url": "https://packages.drupal.org/8"
              }
          ],
      
    • To symlink a local folder that does not have a composer.json file:
          "repositories": [
              {
                  "type": "package",
                  "package": {
                      "name": "drupal/your_project_name",
                      "version": "dev-1.0.x",
                      "type": "drupal-module",
                      "dist": {
                          "type": "path",
                          "url": "path/to/your/local/copy"
                      }
                  }
              },
              {
                  "type": "composer",
                  "url": "https://packages.drupal.org/8"
              }
          ],
      
    • To clone a local folder or issue fork that does not have a composer.json file:
          "repositories": [
              {
                  "type": "package",
                  "package": {
                      "name": "drupal/your_project_name",
                      "version": "dev-1.0.x",
                      "type": "drupal-module",
                      "source": {
                          "type": "git",
                          "url": "git@git.drupalcode.org:issue/your_project_name-0000000.git",
                          "reference": "1.0.x"
                      }
                  }
              },
              {
                  "type": "composer",
                  "url": "https://packages.drupal.org/8"
              }
          ],
      

    where path/to/your/local/copy is the path to your local copy of the project relative to your site’s composer.json and issue/your-project-name-0000000 is the name of an issue fork. It is very important that your local copy of the module come first in the list of repositories, or else Composer will pull down the wrong copy of the module.

    Setting the repository or dist type to path creates a symlink to your local copy. If your local copy is a Git repository, you can clone it instead by using path/to/your/local/copy as the repository or source URL.

  2. Run composer require drupal/your_project_name:@dev to switch to your local copy. Depending upon what branch you are on in the contrib project, you may need to tweak @dev to be something like dev-1.0.x (if you're on the 1.0.x branch, for example) so that the latest commit from the correct branch gets pulled in. You should see a message like this to confirm it’s working:
    ./composer.json has been updated
    Running composer update drupal/your_project_name
    Loading composer repositories with package information
    Updating dependencies                                 
    Lock file operations: 1 install, 0 updates, 0 removals
      - Locking drupal/your_project_name (1.0.x-dev)
    Writing lock file
    Installing dependencies from lock file (including require-dev)
    Package operations: 1 install, 0 updates, 0 removals
      - Installing drupal/your_project_name (1.0.x-dev): Symlinking from path/to/your/local/copy
    Generating autoload files

You can now make changes to your local copy or to an issue fork and have them reflected on your local development environment, without having to nest the local copy of the module as a GIT sub-module. This workflow works well for projects being hosted on systems like Pantheon that use GIT for deployment.

If you clone your local copy instead of symlinking, you need to commit changes in the checked-out contrib project and then run composer update drupal/your_project_name to have them reflected.

Tags

Help improve this page

Page status: No known problems

You can: