Skip to main content
Submodules let you include other repositories inside your project while keeping them separate.

Overview

Use submodules when you need to:
  • Include a library as a subdirectory
  • Share code between projects
  • Pin external dependencies to specific versions
  • Keep separate repositories for components

Commands

Add Submodule

wit submodule add <url> <path>
Example:
wit submodule add https://github.com/lib/utils.git vendor/utils
This:
  1. Clones the repository to vendor/utils
  2. Records the submodule in .witmodules
  3. Stages the changes

Initialize Submodules

After cloning a repo with submodules:
wit submodule init
This registers submodules from .witmodules.

Update Submodules

wit submodule update
Fetch and checkout the recorded commits for all submodules. Combined initialize and update:
wit submodule init
wit submodule update

# Or in one command
wit submodule update --init

Status

wit submodule status
Output:
 a1b2c3d vendor/utils (v1.2.3)
 e5f6g7h vendor/logger (heads/main)
+i9j0k1l vendor/config (modified)
PrefixMeaning
(none)Checked out at recorded commit
+Different commit than recorded
-Not initialized
UHas merge conflicts

Run Command in Submodules

wit submodule foreach <command>
Examples:
# Install dependencies in all submodules
wit submodule foreach "npm install"

# Pull latest in all submodules
wit submodule foreach "wit pull"

# Check status
wit submodule foreach "wit status"

Configuration File

Submodules are recorded in .witmodules:
[submodule "vendor/utils"]
    path = vendor/utils
    url = https://github.com/lib/utils.git
    branch = main

[submodule "vendor/logger"]
    path = vendor/logger
    url = https://github.com/lib/logger.git

Workflow

Adding a Submodule

# Add the submodule
wit submodule add https://github.com/org/lib.git libs/mylib

# Commit the addition
wit commit -m "Add mylib submodule"

Cloning a Repo with Submodules

# Clone the main repo
wit clone https://github.com/org/project.git

# Initialize and update submodules
cd project
wit submodule init
wit submodule update

Updating a Submodule

# Enter the submodule
cd vendor/utils

# Pull latest changes
wit pull

# Go back to main repo
cd ../..

# Commit the update
wit add vendor/utils
wit commit -m "Update utils submodule"

Removing a Submodule

# Remove from index and config
wit submodule deinit vendor/utils
wit rm vendor/utils

# Commit the removal
wit commit -m "Remove utils submodule"

Directory Structure

my-project/
├── .wit/
├── .witmodules          # Submodule configuration
├── src/
├── vendor/
│   ├── utils/             # Submodule (its own .wit)
│   │   ├── .wit/
│   │   └── src/
│   └── logger/            # Another submodule
│       ├── .wit/
│       └── src/
└── package.json

Use Cases

Shared Libraries

# Add your shared library
wit submodule add git@github.com:company/shared-ui.git packages/shared-ui

# Use in your code
import { Button } from './packages/shared-ui';

Pinned Dependencies

# Add at specific version
wit submodule add https://github.com/lib/framework.git vendor/framework
cd vendor/framework
wit checkout v2.1.0
cd ../..
wit commit -m "Pin framework to v2.1.0"

Multi-repo Project

project/
├── frontend/     # submodule: git@company:frontend.git
├── backend/      # submodule: git@company:backend.git
├── shared/       # submodule: git@company:shared.git
└── deploy/       # main repo scripts

Best Practices

Always commit submodule updatesWhen you update a submodule, commit the change to the parent:
wit add vendor/lib
wit commit -m "Update lib to v2.0"
Use branches for trackingIn .witmodules, specify a branch:
[submodule "vendor/lib"]
    branch = main
Be careful with submodule changesChanges inside a submodule must be committed there first, then recorded in the parent.

Troubleshooting

Run init and update:
wit submodule init
wit submodule update
Either commit them in the submodule:
cd vendor/lib
wit commit -am "Fix bug"
Or discard:
cd vendor/lib
wit restore .
Ensure you have push access to the submodule’s repository, then push from within the submodule:
cd vendor/lib
wit push