A submodule is a reference to another Git repository, pinned to one specific commit, living inside your repo at a chosen path.
git submodule add https://github.com/lib/util.git libs/util
This records two things in your parent repo: the URL of the dependency, and the exact commit hash of libs/util to check out. The submodule's files don't become part of your tree — they remain a separate repo.
The pinning is the point. Your parent repo doesn't track "latest of util"; it tracks "this exact commit of util." To upgrade, cd libs/util, git pull, then commit the new hash in the parent.
After cloning a repo with submodules, run:
git submodule update --init --recursive
Alternatives: git subtree (merges the dependency's history into yours, no pinning indirection) or a package manager (npm, cargo, go modules). Most teams prefer package managers; submodules are usually the wrong tool unless you genuinely need source-level vendoring.