The fundamental difference is the composition rule.
In a true component-based approach, you define a configuration, that is:
The list of labels (of SHA1 commits for Git) you need for your project to "work" (i.e. "develop", "compile", "deploy", ...).
Each commit referenced in a configuration helps you to get the exact versions of all trees. There is no exception. Each file of that tree is at the exact version specified by the configuration you have defined.
Note for git1.8.2
"git submodule" started learning a new mode to integrate with the tip of the remote branch (as opposed to integrating with the commit recorded in the superproject's gitlink).
So soon (March 2013), a submodule could reference an upstream HEAD, and not just a fixed SHA1.
(Before 1.8.2) There can be only one label/SHA1 per module. From one common parent repo, you cannot define a module within a module.
(But a module, which is just a reference to an external Git repo, can have its own submodules definition: the parent repo will only refer the first-level submodule, which in turn will reference whatever submodules it had committed within itself)
No so in SVN external: you can define directory externals as well as file external, with or without an explicit revision in it.
You can compose various external properties. For instance:
$ svn propget svn:externals calc
third-party/sounds http://svn.example.com/repos/sounds
third-party/skins -r148 http://svn.example.com/skinproj
third-party/skins/toolkit -r21 http://svn.example.com/skin-maker
The result is not a configuration (one reference for 'calc
'), but a composition of selection rules which define the exact "patchwork" you need in the directory 'calc
'
In short, you cannot "compute" one SHA1 for a 'calc
' submodule which would be the exact equivalent of a bunch of svn:external
properties on a 'calc
' SVN directory.