Git Worktree Submodules Not Initialized: How to Fix It
Prepared and checked using AI. Sources are linked in the article.
If git worktree submodules are not initialized, enter the new agent worktree and run git submodule update --init --recursive before the agent starts reading or changing code. With the checkout procedure, --init initializes missing submodules and --recursive includes nested ones. A configured update procedure can prevent the command from populating a submodule, so check the result; --checkout explicitly selects checkout of the recorded commit.
A submodule is a separate repository: the superproject stores a gitlink to a commit and uses .gitmodules to map the submodule name to its path. An empty directory is consistent with a submodule that has no working directory yet. An initialized submodule in your main checkout does not establish that its files are present in a newly created agent worktree. Git warns that submodule support across multiple worktrees is incomplete and recommends against multiple checkouts of a superproject. One alternative for an agent that needs a separate checkout is a separate clone: git clone --recurse-submodules initializes submodules after cloning. For more on what a worktree isolates, see Git Worktrees: Why AI Agents Need Them.
Initialize the agent worktree
For example, suppose main is the starting branch, agent-fix is the agent’s branch, and ../agent-fix is its new worktree directory:
git worktree add -b agent-fix ../agent-fix main
cd ../agent-fix
git submodule status
git submodule update --init --recursive
git submodule status --recursive
Run the update inside the new worktree. That makes the command act on the branch and submodule paths the agent will use. --init registers submodules that have not been initialized; update obtains missing submodule commits and, with the checkout procedure, populates their working directories; --recursive includes nested submodules. Without --recursive, a top-level submodule may contain another empty submodule path.
Read git submodule status before and after the update. A leading - means a submodule is not initialized. A leading + means its checked-out commit differs from the commit recorded in the containing repository, while U indicates a merge conflict. A status line without those prefixes is the expected state for a submodule checked out at its recorded commit. git submodule status --recursive extends the check to nested submodules.
When no update procedure is configured, update checks out the commit recorded by the superproject, leaving the submodule at a detached HEAD. That is appropriate when the agent needs the dependency version pinned by the task branch. Do not substitute git submodule update --remote: --remote uses a remote-tracking branch instead of the superproject’s recorded commit, which can change the code the agent sees.
Check whether the path is a submodule
Do this before treating every empty directory as the same problem. Suppose vendor/parser is the missing path. These commands inspect the new worktree’s index and submodule state:
git submodule status -- vendor/parser
git ls-files --stage -- vendor/parser
git submodule status --cached -- vendor/parser
git ls-files --stage prints the indexed mode, object ID, stage, and path. A submodule appears as a gitlink entry with mode 160000; an ordinary tracked directory is represented by its files instead. git submodule status --cached shows the commit recorded in the superproject’s index, even when the working directory is not populated. If neither command identifies a submodule at that path, check the branch and path spelling before running more submodule commands.
Check .gitmodules in the new worktree as well. Each submodule entry has a submodule.<name>.path and submodule.<name>.url, and may set submodule.<name>.update to checkout, rebase, merge, or none. The name need not match the path if it was customized. A branch can have a different .gitmodules file or a different set of submodule paths, so use the agent worktree’s version of that file when diagnosing it.
To initialize only the dependency needed for this task, use its path:
git submodule update --init --recursive -- vendor/parser
The path after -- limits the command to that submodule. This can avoid cloning unrelated dependencies when an agent needs only part of a large repository. If the agent must search or test the whole project, initialize all required submodules instead; an absent dependency can make its view of the code incomplete.
If the directory stays empty
First, look at the status prefix and the command’s error output. A leading - after an attempted update means initialization did not complete. If the command could not clone or fetch the repository, check that the URL in .gitmodules is correct and that the environment running Git can access it. The update command cannot check out a recorded commit it cannot obtain.
Submodule settings can also affect initialization and checkout. With submodule.active configured, git submodule init without a path initializes only active submodules. A submodule.<name>.active setting can mark one submodule inactive. Inspect the effective settings before changing them:
git config --show-origin --get-regexp '^submodule\.'
git config --show-origin includes the file that supplied each setting. If the intended submodule was excluded, pass its path explicitly to git submodule update --init --recursive -- vendor/parser. Also look for submodule.<name>.update in the output. merge and rebase select different update procedures; none skips the update and can leave the dependency unpopulated despite --init --recursive. To override that setting and check out the superproject’s recorded commit, run:
git submodule update --init --recursive --checkout -- vendor/parser
The command-line --checkout option takes precedence over the configured update procedure. Be careful when changing repository configuration for an agent: by default, linked worktrees share the repository config file. A change intended for one worktree may affect the others.
If a submodule URL changed on the task branch, git submodule sync --recursive copies URLs from .gitmodules to the configuration of already initialized submodules. Follow it with git submodule update --init --recursive. sync only affects submodules that already have a configured URL, so it does not replace --init. In a repository whose agent worktrees need different submodule URLs at the same time, account for their shared configuration before syncing one branch’s URL across the repository.
Avoid git submodule update --force as a routine repair. With the checkout procedure, --force can discard local changes inside the submodule. Likewise, do not delete and recreate a worktree merely because a submodule is empty: initialization is the direct first step, and deleting a worktree can discard agent changes.
Make initialization part of the agent setup
Treat submodule preparation as a step between creating a worktree and launching an agent. The sequence is: create the worktree, run the recursive update there, check recursive status, and then start the agent. If setup stops because a required submodule cannot be fetched or an update setting skips its checkout, resolve that failure before asking the agent to edit code that imports or builds against it.
When agents work on separate branches, repeat the check in each worktree. The superproject commit on one branch may pin a different submodule commit from another branch. After a branch change or merge that changes a gitlink, run git submodule update --init --recursive again in the affected worktree, using --checkout if its update setting requires an override. Review a proposed submodule change as a commit-pointer change as well as reviewing edits in the superproject; see How to Review AI-Generated Code Efficiently for the broader review workflow.
A separate clone gives an agent a separate repository configuration and working directory, at the cost of managing another clone instead of a linked worktree. Choose it when you need to avoid the documented worktree and submodule limitations or shared settings.
Where Parallel Code fits
Parallel Code is our free, open-source (MIT) desktop app for macOS and Linux that runs AI coding agents in parallel, each in its own git worktree. Initialize and check required submodules in each agent worktree before the agent uses them. Its diff-first review surface helps you inspect the resulting changes.
Frequently asked questions
Why is the submodule populated in my main checkout but empty in the agent worktree?
The main checkout’s populated directory does not mean the new worktree has checked out that submodule. Enter the agent worktree and run git submodule update --init --recursive, then check git submodule status --recursive there. If it remains empty, inspect the update setting.
Do I need both --init and --recursive?
--init handles submodules that have not been initialized; --recursive continues into submodules nested inside them. Use both when the agent needs the complete dependency tree pinned by the superproject, then verify that the configured update procedure populated it.
Should I use git submodule update --remote instead?
Use the ordinary update command with the checkout procedure when you want the commit recorded by the agent branch. --remote selects a remote-tracking branch, so it serves a different purpose: intentionally advancing the submodule beyond the recorded commit.
Can I initialize just one submodule for one agent?
Yes. Run git submodule update --init --recursive -- vendor/parser from that agent’s worktree, replacing the example path with the submodule path. Verify that the agent’s task does not also depend on other uninitialized submodules.