Why Would One Use a Dev-Master Branch?

We've all done it, especially in the Drupal world. We've searched and searched for that perfect contrib module that does almost everything we need. When we find it, we rejoice, only to find out that there's no alpha, beta, release-candidate, or stable release available. We comb the commits and repo, looking for clues as to why it's as tagless as a quality cotton undershirt (no, I'm not being paid by big clothing. However, if they were interested in sponsoring me for any reason, I'm open to that conversation.) Nothing sticks out, like a quality cotton undershirt with no tag.

Sorry, I just bought some new shirts and this is the only analogy I can think of because they're soooo soft, but I won't mention the brand until I get sponsor money.

Maybe it's something else. Perhaps we've run into a problem with an external API changing and the contrib module hasn't been keeping up. We go to the issue queue to start an issue, but like good, little developers, we first search for something like what we've run into. A-ha, there it is! Someone else has found it, fixed it, and the maintainer committed it, but we don't have a tagged release yet. What are we to do? We want to manage our dependencies with composer, but we haven't learned how to use composer.json to manage patches yet. We decide to throw caution to the wind and composer require drupal/some_module:dev-master

Feel good about it?


The Risks of Non-Tagged Dependencies

Recently, I ran into an issue where another developer on a project was doing some updates and ran the ever-troublesome composer update. Why is this a risk? Well, to put it simply, if your package is locked at dev-master then it's not locked at a tag so it's only locked to a branch. Since the dev-master branch is where the updates happen, it's a good chance that the package maintainer is eventually going to merge in a few commits to this branch and make some updates. It's even possible that the functionality will be changed by A LOT down the line.

Imagine, if you will, that we found that Xyz API had changed significantly and went through the process outlined above. We found the right module with the updates committed from the issue queue and we required the dev-master package.

Six months later the project maintainer decides to commit and merge a completely revamped version of the module to dev-master. A security PSA is released on d.o and it becomes time to make some updates.

[ [email protected] ~/docroot ]$ composer update
Using version dev-1.x for drupal/xyz_module
./composer.json has been updated
Gathering patches for root package.
Loading composer repositories with package information
15/15:        https://ftp.drupal.org/files/projects/xyz_api-8.x-dev-master.zip    
Finished: success: 15, skipped: 0, failure: 0, total: 15 
Package operations: 13 installs, 2 updates, 0 removals
Gathering patches for root package.
Gathering patches for dependencies. This might take a minute.
Writing lock file
Generating autoload files

What just happened? Well, if we look at the diff of our composer.lock file, we'll notice that there's been a change right around here:

"name": "drupal/xyz_module",
"version": "dev-1.x",
"source": {                  
  "type": "git",
  "url": "https://git.drupal.org/project/xyz_module",
-    "reference": "722692cd27591385dc694a04561fd1a9ace1c78f"
+   "reference": "91385dc7cd27569ace1c94a0456226a78f921fd1"


Now we don't have the same commit, and if we're not paying attention then stuff is going to break.

What Should Have Happened

We have a couple of options here. Option one would be to include the changes from the issue queue as a patch within the composer.json file. That way, the next time we run composer update we'll see the patch fail and know it may be time to check the issue associated with the patch for resolution.

Alternatively, we can lock dev-master at a certain commit. This is done very similarly to the way that we lock a package to a version. Instead of a ~ or^, we're going to explicitly declare the commit hash.

composer require drupal/xyz_module:dev-master#722692cd27591385dc694a04561fd1a9ace1c78f

Where everything after the # is the hash number of the commit. This can usually be found in the URL of a repo or, if you've tested the d.o gitlab waters, you may notice the icon to the left of a commit message that shares similarities with a copy icon.

Image of a copy to clipboard icon

Now, use that freshly copied hash and lock in your dev-master to prevent tears in the future.  Trust me on this.