States

status reports exactly one of seven states for each submodule; the first state whose condition matches wins.

The seven states

State

Meaning

In the demo

What update does

ok

HEAD is the locked commit, and no other target is available locally

fpga.core, sdk

Nothing: up to date

behind

update would select another mode, ref or commit than the lock entry records, or there is no lock entry yet

kernel, u-boot

Moves the submodule to the target

drift

HEAD differs from the locked commit, or the locked tag now points elsewhere or is gone

fpga.core after its tag moved

Checks out the target and records it

dirty

The submodule working tree has uncommitted changes

app

Refuses (status 3)

uninitialized

The submodule is not checked out

theme, fresh

Initializes it offline if its repository exists; otherwise refuses without --fetch

missing-ref

The configured ref is invalid or not found in the local refs

broken

Refuses (status 3)

unmanaged

The submodule has no lsm-mode key

legacy

Skips it; refuses when it is named

The states come from the demo superproject in its first state:

NAME        PATH               MODE         REF      LOCK                   HEAD     STATE
kernel      kernel             tag-pattern  v6.6.*   8106f61 (v6.6.9)       8106f61  behind
u-boot      bootloader/u-boot  branch       main     29b295c                29b295c  behind
fpga.core   ip/fpga-core       tag          v2.3.1   556baa1                556baa1  ok
crypto lib  libs/crypto lib    commit       5da6927  5da6927                5da6927  ok
legacy      vendor/legacy      -            -        -                      2f54e11  unmanaged
tools       tools/nested       branch       develop  3e8e307                3e8e307  ok
theme       docs/theme         tag          v1.0.0   05f49f3                -        uninitialized
fresh       third_party/fresh  tag-pattern  v1.*     f2de3e1 (v1.1.0)       -        uninitialized
app         apps/app           tag          v1.2.0   cfa9d86                cfa9d86  dirty
sdk         sdk                tag-pattern  v*       6308203 (v3.0.0-rc.2)  6308203  ok
mirror-lib  libs/mirror        branch       stable   71eb52c                71eb52c  ok
broken      libs/broken        tag          v9.9.9   52c4bdb (v1.0.0)       52c4bdb  missing-ref
signed      libs/signed        tag          v1.0.0   5d1133e                5d1133e  ok
quirky      libs/quirky        tag          v1.0.0   64eca61                64eca61  ok

Troubleshooting explains how to resolve each state.

Precedence

The first matching state wins, in this order:

  1. unmanaged: there is no lsm-mode key in .gitmodules.

  2. uninitialized: the submodule is not checked out.

  3. dirty: the working tree has uncommitted changes.

  4. missing-ref: the configured ref is invalid, or does not resolve in the local refs.

  5. drift: a lock entry exists, and either HEAD differs from the locked commit, or, in tag and tag-pattern mode, the locked tag now points to a different commit or no longer exists.

  6. behind: there is no lock entry yet, or update would select another mode, ref or commit than the lock entry records.

  7. ok: none of the above.

Precedence of the submodule states status checks the states in this order, and the first one that matches wins: 1. unmanaged: there is no lsm-mode key in .gitmodules; 2. uninitialized: the submodule is not checked out; 3. dirty: the working tree has uncommitted changes; 4. missing-ref: the configured ref is invalid or not found in the local refs; 5. drift: HEAD differs from the locked commit, or the locked tag moved; 6. behind: no lock entry yet, or update would select another target; 7. ok: none of the above. Checked from top to bottom; the first match wins 1 unmanaged there is no lsm-mode key in .gitmodules 2 uninitialized the submodule is not checked out 3 dirty the working tree has uncommitted changes 4 missing-ref the configured ref is invalid or not found in the local refs 5 drift HEAD differs from the locked commit, or the locked tag moved or is gone 6 behind no lock entry yet, or update would select another target 7 ok none of the above

status checks the conditions from top to bottom and reports the first state that matches.

A dirty submodule is therefore reported as dirty even when a newer tag exists, and a submodule whose tag moved is reported as drift even when update would also select a newer tag.

Details

  • Local refs only. States are computed from the refs that exist locally. A new tag or branch commit on the remote shows up only after fetch.

  • Branch mode. behind compares with the remote-tracking branch origin/<branch> as of the last fetch.

  • Never downgrade. In tag-pattern mode, the locked tag stays a candidate while it exists and matches the pattern, even when it is a pre-release. The demo’s sdk is ok at v3.0.0-rc.2 although v2.9.0 is the newest stable tag; Tracking modes and resolution explains the rule.

  • Detached HEAD is the normal state of a submodule and not reported.

  • What counts as dirty. Uncommitted changes to tracked files. Untracked files do not count, and neither does a nested submodule that is only checked out at another commit; modified files inside a nested submodule do. The demo’s tools is ok although its nested submodule is at another commit.

  • Native keys. update = none and ignore = all in .gitmodules do not change the state; the demo’s quirky has both and is ok.

  • The lock file in the working tree is compared, so a staged update already shows ok. verify checks the committed state.

  • Invalid configuration. An lsm-mode that is not one of the four modes is an error for the whole command, not a state; see .gitmodules.

Where the states appear

  • Table. The STATE column of lazysubmodules status.

  • Porcelain format. Field 8 of status --porcelain=v1. The state names are part of the stable format.

  • Terminal interface. The STATE column of the table, and the preview, which explains why the submodule is in its state.

Colors

In a terminal, status and the terminal interface color the states. This site uses the same color families for its state labels.

State

Terminal color

ok

green

behind

yellow

drift

red

missing-ref

red

dirty

magenta

uninitialized

gray

unmanaged

gray

status uses colors only when standard output is a terminal, NO_COLOR is unset or empty, and TERM is not dumb; see Colors.

See also