This will put all of my Drupal modules into docroot/modules/contrib (relative to my composer.json).

But say I need to patch twig_tweak, for example. I would need to clone the git repo and check it out at whatever the most recent dev version is.

To do that with composer, you can run

composer require drupal/twig_tweak --prefer-source

If you've already installed twig_tweak, you'll have to remove it first (rm -rf docroot/modules/contrib/twig_tweak)

Now you'll have the module installed with the .git folder so you can track any changes you need to make. If you go into the module's directory (cd docroot/modules/contrib/twig_tweak) and run git branch -v you can see that it also pulls info for the dev branch, assuming you're on the main branch.

You can now make your adjustments, and create a patch by running git diff > name-of-patch.patch.

If for some reason your patch is specific to your use case and you don't need/want to push it upstream somewhere, you can store this .patch file locally and add it to your composer but use a relative path. I usually put custom patches in ./patches, so an example patch would add this to my composer.json inside the 'extras' object: