You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
UpdateSubmodules() reports success without checking out the recorded commit when submodule.<name>.update is none/merge/rebase #247
GitSubmoduleUpdateBuilder documents the verb as "Checks out the commits the superproject's gitlinks record" (GitIntegration/Builders/GitSubmoduleUpdateBuilder.cs:12). Its argument vector (about lines 150-160) emits submodule update [--progress] [--init] … with no update-mode flag, so git applies submodule.<name>.update from .gitmodules or .git/config:
none: git prints Skipping submodule 'sub' and exits 0, leaving the submodule wherever it was.
merge / rebase: git merges or rebases the submodule's current branch onto the recorded commit instead of detaching at it.
Failure scenario (reproduced with git 2.43)
The superproject's gitlink records commit s2, and the submodule is checked out at s1.
.gitmodules contains update = none, which --init copies into .git/config.
await repo.UpdateSubmodules().Initialize().ExecuteAsync() succeeds, and the submodule is still at s1.
The same command with --checkout added prints checked out '…', and the submodule is at s2.
A caller that relies on the verb's contract, for example to make a CI checkout match the superproject, silently gets the wrong tree.
Suggested fix
Always emit --checkout. git documents its main use as overriding submodule.$name.update, so this makes the verb match its doc comment on every host.
Optionally add an explicit opt-in, such as HonourConfiguredUpdateMode(), for callers who want a .gitmodules-authored none respected. Overriding none by default is a deliberate choice, but it is the only behaviour consistent with the documented contract.
Acceptance criteria
An argument-vector test asserts --checkout by default.
An integration test with submodule.sub.update=none, and one with rebase, leaves the submodule detached at the gitlink-recorded commit after UpdateSubmodules().
Priority: Medium. UpdateSubmodules() reports success while leaving the submodule on the wrong commit whenever .gitmodules sets update = none, merge or rebase. That breaks the verb's documented contract, for example for CI checkouts. The fix is to always emit --checkout, but overriding none by default is a behaviour choice the maintainer should confirm, possibly with an opt-out.
Area / suggested assignment: GitIntegration GitSubmoduleUpdateBuilder argument vector.
Activity
matt-edmondson commentedon Oct 18, 2026
Triage
UpdateSubmodules()reports success while leaving the submodule on the wrong commit whenever.gitmodulessetsupdate = none,mergeorrebase. That breaks the verb's documented contract, for example for CI checkouts. The fix is to always emit--checkout, but overridingnoneby default is a behaviour choice the maintainer should confirm, possibly with an opt-out.GitSubmoduleUpdateBuilderargument vector.--ignore-submodules=none. No duplicate found.Generated by Claude Code