Skip to content

UpdateSubmodules() reports success without checking out the recorded commit when submodule.<name>.update is none/merge/rebase #247

Open

Description

@matt-edmondson

What's wrong

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)

  1. The superproject's gitlink records commit s2, and the submodule is checked out at s1.
  2. .gitmodules contains update = none, which --init copies into .git/config.
  3. await repo.UpdateSubmodules().Initialize().ExecuteAsync() succeeds, and the submodule is still at s1.
  4. 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().

Activity

  1. matt-edmondson commented on Oct 18, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions