A submodule is a reference to another Git repository inside a project. Used to include an external library or shared code stored in a separate repository.

💡 A submodule stores a reference to a specific commit of the external repo, not the code.


Add a submodule

# Add a repo as a submodule to a specific path
git submodule add <URL> <path/to/place>

# Example
git submodule add https://github.com/luizdepra/hugo-coder.git themes/hugo-coder

# Commit changes
git commit -m "Add submodule: themes/hugo-coder"
git push

After this, the project will have:

  • .gitmodules file - submodule configuration
  • Submodule folder - a reference to the external repo

Clone a project with submodules

# Option 1: clone with submodules from the start
git clone --recursive <URL>

# Option 2: if already cloned without submodules
git submodule update --init --recursive

Update a submodule

# Go into the submodule and pull changes
cd themes/hugo-coder
git pull origin main

# Go back to root and commit the new submodule commit
cd ../..
git add themes/hugo-coder
git commit -m "Update submodule: hugo-coder"
git push

Or one command from root:

# Update all submodules to latest remote commits
git submodule update --init --recursive --remote

# Commit the updated references
git add .
git commit -m "Update all submodules"
git push

⚠️ --remote fetches latest commits from remote repos. Without it - only commits already recorded in .gitmodules.


Remove a submodule

# 1. Deinitialize the submodule
git submodule deinit -f themes/hugo-coder

# 2. Remove from index and working directory
git rm -f themes/hugo-coder

# 3. Remove internal data (optional but recommended)
rm -rf .git/modules/themes/hugo-coder

# 4. Commit changes
git commit -m "Remove submodule: themes/hugo-coder"
git push

Useful commands

# Show status of all submodules
git submodule status

# Show which commits are pending update
git submodule foreach 'git log -1 --oneline'

# Sync submodule URLs (if remote changed)
git submodule sync --recursive

# Run a command in all submodules
git submodule foreach 'git fetch'

Typical issues

# Submodule folder is empty after clone
→ git submodule update --init --recursive

# "fatal: not a git repository" inside submodule
→ Delete the submodule folder and run:
  git submodule update --init

# Submodule version conflict during merge
→ Choose the correct commit version:
  git add themes/hugo-coder
  git commit -m "Resolve submodule conflict"