What's the difference between `plugins {}` and `pluginManagement.plugins {}` in `settings.gradle`

(I asked this question on StackOverflow (What's the difference between `plugins {}` and `pluginManagement.plugins {}` in `settings.gradle` - Stack Overflow) but received no response, so I’m asking it here now. Thank you in advance)

Basically the title.

I couldn’t find a simple comparison anywhere, explaining the differences between these two:

pluginManagement {
    repositories {
        gradlePluginPortal()
        google()
    }

    plugins {
        id "com.some.awesomeplugin" version "1.2.3"
        id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
    }
}

// And these:
plugins {
    id "com.another.greatplugin" version "2.1.37"
    id "com.android.application" version "7.3.0" apply false
}

I’m aware that there can be 3 types of plugins in Gradle:

  1. Project plugins, whose apply() callback is called when the individual build.gradle files are evaluated:
class BuildPhasePlugin : Plugin<Project>
  1. Settings plugins, whose apply() callback is called when the settings.gradle file is evaluated:
class SettingsPhasePlugin : Plugins<Settings>
  1. Initialization plugins, whose apply() is called when initialization script (init.gradle) is evaluated:
class InitPhasePlugin : Plugin<Gradle>

I suppose these 3 types of plugin are somehow related to the plugins {} block they can be applied in in settings.gradle?

pluginManagement { plugins { ... } } does not apply any plugin and does not add them to any classpaths, and thus apply false is a no-op and should imho actually trigger a syntax error.

This block just centrally defines the versions for plugins when they are used in other places without a version.
Nowadays I would not use this block at all anymore, but instead use a version catalog to centrally define the versions including plugin versions.

The plugins { ... } block on top-level actually applies the specified settings plugins (or just adds them to the classpath when used with apply false.