Git worktree vs submodule: when to use each
These blocks describe different cases, not one script. Choose the case that matches your repository. Replace example branch names, file paths and VERIFIED_COMMIT before use. Abort commands apply only to their active operation; do not run both alternatives.
Short answer
Use a Git worktree when you need another checkout of the same repository for parallel tasks or branch review. Use a submodule when one repository must record a particular commit of another repository as a dependency. They solve different boundaries: another working directory for shared history, or a separately versioned repository whose selected commit is recorded by a parent.
| Decision | Worktree | Submodule |
|---|---|---|
| History | Same repository, shared objects and most references | Separate child repository, parent records a commit |
| Working files | Separate HEAD, index and working directory | Child checkout, parent HEAD pin and staged pin can differ |
| Version choice | A branch or commit of the same repository | A selected child commit, not just .gitmodules |
| Update | Review and integrate the chosen branch | Update checkout to recorded pin; --remote is a separate choice |
| Main limit | Normally one checkout per branch; not a permission sandbox | Multiple-worktree support is incomplete; child work is separate |
The example and its prerequisites
First decide who owns the history. Two agents testing alternative fixes to one application usually need separate branches and working trees. An application consuming a library with its own release process may need a pinned dependency. Neither mechanism is a permission sandbox: filesystem and agent permissions remain separate. Pick the history relationship before choosing a convenient folder layout.
Inspect before changing anything
A linked worktree has its own HEAD, index and working files while sharing the repository's object store and most references. This lets you keep your current edits in one checkout while reviewing another branch elsewhere. Git normally prevents the same branch from being checked out in two worktrees at once. Shared objects do not mean that unstaged edits automatically appear in the other directory.
git status --short
git branch --show-current
git worktree listKeep a reference or a separate checkout
In the worktree example, inspect status and create a new review/worktree branch in ../topic-review. Inspect that checkout with git -C and compare its commits before merging a selected result. The separate directory reduces accidental task mixing; it does not make two changes compatible. Run the relevant checks after integration, and avoid having two tools mutate the same checkout at the same time.
git worktree add -b review/worktree ../topic-review HEAD
git -C ../topic-review status --short
git -C ../topic-review branch --show-currentThe first workflow
A submodule is a separate repository at a path in the parent. The parent's committed tree records a gitlink, normally mode 160000, naming a child commit. The parent's index can stage a different child commit; the child's current checkout can differ from either. .gitmodules describes the path and URL, but the selected dependency version comes from the recorded commit, not merely from that file.
Choose the other outcome deliberately
For an existing dependency at deps/library, inspect submodule status, the parent's HEAD gitlink, the staged gitlink and the child's HEAD separately. A parent pull can change the recorded pin without moving the child checkout to it. A normal submodule update checks out the recorded selection; --remote deliberately follows a remote-tracking choice and is a different version-update decision. Do not use it just to make a dirty status disappear.
git submodule status -- deps/library
git ls-tree HEAD -- deps/library
git ls-files --stage -- deps/library
git -C deps/library rev-parse HEAD
git --no-optional-locks -C deps/library status --shortLimits and exceptions
Git documents incomplete support for submodules in multiple worktrees. Do not assume that adding --recursive turns any linked-worktree setup into a supported isolated environment. For a project combining them, check the documented limitations, test its actual checkout/update workflow and consider a separate clone when independent repository state is required. This comparison is not a universal recipe for worktree-plus-submodule automation.
Conflicts and cleanup
Before removing a worktree, inspect its uncommitted files and committed branch, then use git worktree remove rather than deleting the directory blindly. Keep the wanted branch or a reviewed merge. Before changing a dependency pin, commit and publish the child change through its own repository workflow so another clone can obtain it, then record the intended pin in the parent. Parent and child history are reviewed separately.
git -C ../topic-review status --short
git worktree remove ../topic-review
git worktree listVerify the result
Verification is different for each mechanism. For worktrees, confirm the branch, status and selected integration result. For a submodule, compare all three states and confirm the child object can be fetched by the intended audience. A clean parent status does not necessarily mean every child working tree is clean. Neither mechanism stores a permanent backup of uncommitted files.
git worktree list
git submodule status -- deps/libraryCommon questions
Why use worktree? To work on another branch of the same repository without replacing your current checkout. When use submodules? When a separately versioned dependency should be pinned in a parent. Why avoid them? Their separate checkout and update rules add coordination cost. Alternatives include a package manager, vendoring, subtree or a separate clone; choose by version ownership and delivery needs, not a universal winner.
Review the operation in FluxGit
Use FluxGit’s visual history and patch view to review the operation and the relevant commits. Keep the branch, sharing and local-file checks in this example. The download page lists the currently available builds and platforms.