Home / Alt manpages / git-status(1)

  • git-status(1)
  • User command
  • linux

Read Git Status Without Misreading the Two-Column Codes

You will finish with a reliable way to inspect a Git worktree, tell staged changes from unstaged ones, find untracked files, and choose a stable output format for scripts. The examples match Git 2.43.0, the version installed on this machine. Allow about ten minutes. You need a Git repository and an ordinary shell account; none of the checks below requires sudo.

Checkpoint

This guide uses git status as an inspection command. It does not add, commit, discard or delete anything. Treat any command containing git add, git restore, git reset or git clean as a separate state-changing decision.

1. Confirm the repository and Git version

Change to the repository you want to inspect, then ask Git for its version and repository state:

$ cd /path/to/repository
$ git --version
git version 2.43.0
$ git status

The final command uses the default long format. A clean repository normally reports:

On branch main
nothing to commit, working tree clean

Your branch name may differ, and a repository without an upstream may omit tracking information. If Git says it is not a repository, check the path before trying a different command. Running status from a subdirectory is valid: the displayed paths are normally relative to that directory, which is convenient for copying a path into a command.

2. Understand what status compares

Git status compares three places: the current HEAD commit, the index, and the working tree. The index is also called the staging area. A change in the index is prepared for the next commit. A change only in the working tree is not prepared yet. An untracked path exists on disk but is not in the index, unless an ignore rule hides it.

This distinction explains a common surprise: one file can appear twice. The first copy of its change is staged, while a later edit is unstaged. Status is describing two separate comparisons, not contradicting itself.

Make a small, reversible test in a disposable repository if the two comparisons are unfamiliar:

$ printf 'first line\n' > example.txt
$ git add example.txt
$ printf 'second line\n' >> example.txt
$ git status --short

Expected output is similar to this:

AM example.txt

The first column, A, says the index contains an added file. The second column, M, says the working tree differs from the index. If you do not want to keep this test, remove the disposable repository afterwards with your normal careful file-management process. Do not use a broad cleanup command in a real worktree merely to make status look clean.

3. Use short output for a quick review

Use --short, or its -s spelling, when the long explanatory text would distract from the paths:

$ git status --short
AM example.txt
?? notes.txt

The two characters are conventionally called XY. X describes the index and Y describes the working tree. Read the useful cases as follows:

CodeMeaning
M  Modified in the index, with no later worktree change.
 MModified in the worktree, but not staged.
MMModified once in the index and again in the worktree.
A  Added to the index.
D  Deletion staged in the index.
??Untracked and not ignored.
!!Ignored, but visible because --ignored was used.

A blank position is meaningful, so copy the two columns exactly when documenting a state. During a conflict, codes containing U indicate an unmerged path. Stop before committing and resolve the conflict using the project workflow; status is reporting the problem, not selecting the correct side for you.

4. Inspect branch and stash information

Add --branch to short output when branch or upstream details matter:

$ git status --short --branch
## main...origin/main [ahead 1]
 M src/config.ini

The exact tracking line depends on your branch and remote. The ahead and behind counts are shown when an upstream and the relevant commits are available. To include the number of stash entries, use the newer explicit option shown in the installed manual:

$ git status --short --branch --show-stash
## main...origin/main
# stash 2

The stash line is omitted when the count is zero. Neither command changes the branch, remote, index or stash.

5. See untracked and ignored paths deliberately

By default, Git shows untracked files and directories, but it does not show ignored paths. This prevents build output and editor caches from overwhelming a normal review. Use the option explicitly when checking whether a new file is being hidden:

$ git status --short --ignored
!! build/
?? draft-notes.txt

The default ignored display mode is traditional. For more detail inside untracked directories, use --untracked-files=all. For speed in a very large worktree, --untracked-files=no suppresses untracked paths:

$ git status --short --untracked-files=no
 M src/config.ini

That faster output is incomplete by design. It can hide a newly created file you forgot to add, so use it only when you have another way to account for new files. The option must be attached when using the short form, as in -uno; -u no is not the documented spelling.

6. Choose porcelain output for scripts

Do not parse the human long format. Its contents can change, and ordinary short output can be affected by user configuration. Use porcelain output instead:

$ git status --porcelain=v1
 M src/config.ini
?? draft-notes.txt

Porcelain version 1 keeps the short-style status while disabling colour and making paths relative to the repository root. For a parser that must preserve arbitrary filenames, use NUL-terminated output:

$ git status --porcelain=v1 -z | od -An -t x1
20 4d 20 73 72 63 2f 63 6f 6e 66 69 67 2e 69 6e
69 00

Do not copy the displayed hexadecimal bytes as a filename result. The important check is the 00 terminator. With -z, Git does not quote unusual characters, and rename paths use NUL separation. A shell loop should therefore read NUL records rather than splitting on lines.

Porcelain version 2 provides more machine-readable detail, including optional branch headers when --branch is supplied. Its changed-entry records are more structured, but parsers must still accept records in an undefined order and ignore headers they do not recognise.

7. Investigate slow or surprising status

Finding untracked files can be expensive in a large worktree. First run ordinary status again: an existing cache may already make the second run faster. If untracked files are not relevant to this particular check, use --untracked-files=no and remember that the result is partial.

For repeated work in a large repository, the manual documents an untracked cache and FSMonitor as possible performance aids. They affect Git's index or configuration, so do not enable them blindly on a managed checkout. Check the repository's contribution or operations guidance first. A status command can also refresh cached index stat information and write the index as an optimisation. Background scripts that collide with that lock can use git --no-optional-locks status, provided they accept the limitations of avoiding optional index writes.

Submodules have their own worktrees. The default status mode hides many submodule details. Use --ignore-submodules=none when you need Git to consider untracked content, modified content and a changed submodule commit. This can be slow and noisy, so use it for a focused check rather than every prompt.

Done means

  • You confirmed the repository and installed Git version.
  • You can distinguish index changes in column X from worktree changes in column Y.
  • You checked untracked and ignored paths when a clean-looking result needed proof.
  • You use --porcelain=v1 or version 2 instead of parsing human output in scripts.
  • You know that --untracked-files=no makes status faster by hiding information.
  • You have not changed the repository while inspecting it.