Skip to content
masterclass Buddy

Git · Command

git status

git status reports the state of your working tree. It lists what is staged for the next commit, what has changed but is not staged, and which files Git is not tracking.

Last updated

How it works

Git makes three comparisons. It compares HEAD with the index, which gives the changes that a plain commit would record. It compares the index with the working tree, which gives edits you have not staged yet. It also scans for files that are neither tracked nor ignored. The default long output is meant for people and includes hints about what to do next. The short format (-s) shows each path with a two-letter XY code. The --porcelain format looks like the short format, but it is meant for scripts and stays stable. By default, status also refreshes the cached stat information in the index and writes it back, so later commands don't have to repeat that work.

Syntax

git status [<options>] [--] [<pathspec>…]

Parameters

NameTypeDescription
-s, --shortflagPrints the compact XY-code format.
-b, --branchflagAdds the branch name and upstream tracking info to short output.
--show-stashflagShows how many stash entries exist.
--porcelain[=<version>]flag (v1 | v2)Machine-parseable output that stays stable. Defaults to v1.
--longflagHuman-readable long format. This is the default.
-v, --verboseflagAlso shows the staged diff. Give it twice to also show the unstaged diff.
-u[<mode>], --untracked-files[=<mode>]no | normal | allControls how untracked files are listed. With no mode given, it means all.
--ignore-submodules[=<when>]none | untracked | dirty | allControls which submodule changes are ignored. Defaults to all.
--ignored[=<mode>]traditional | no | matchingAlso lists ignored files.
-zflagEnds entries with NUL instead of LF. Implies --porcelain=v1 unless another format is given.
--column[=<options>], --no-columnflagShows untracked files in columns.
--ahead-behind, --no-ahead-behindflagTurns detailed ahead/behind counts against the upstream on or off. On by default.

Key points

  • For scripts, use --porcelain. Its output is designed to stay the same across Git versions, and your personal settings such as colour do not change it.
  • If you run it from a subdirectory, the human-readable output shows paths relative to where you are, which makes them easy to copy and paste. Porcelain output always shows paths relative to the repository root.
  • In short format, the two letters XY mean different things depending on the situation. Normally X is the index and Y is the working tree. During an unresolved conflict, they describe the two sides of the merge. '??' marks an untracked file.
  • With -v you also see the staged diff, just like git diff --cached. Pass -v twice to also see the unstaged diff.
  • --porcelain=v2 adds header lines such as branch.oid, branch.head and branch.ab, plus file modes and object names for each changed entry.
  • In large repositories, setting core.untrackedCache=true, optionally together with core.fsmonitor, means status only rescans directories that have changed since the last run.
  • Add -b to short output to get a '## branch tracking-info' header line, and --show-stash to see how many stash entries you have.

Common mistakes

  • Don't parse the default long output in scripts. Its wording and layout can change between releases.
  • status writes the refreshed index back to disk. If you run it in the background, for example from an editor or a prompt, it can block other Git processes. Use git --no-optional-locks status there.
  • The mode for -u has to be attached directly to the flag. '-uno' works, but '-u no' does not.
  • -uno (or status.showUntrackedFiles=no) is the fastest setting, but it hides new files completely, so they are easy to forget to commit.

Example: Fail a script if the working tree is dirty

#!/usr/bin/env bash
set -euo pipefail

# Human-friendly overview with branch info
git status -sb

# Stable, script-safe check (no lock contention)
changes=$(git --no-optional-locks status --porcelain=v1)
if [ -n "$changes" ]; then
  echo "Working tree is not clean:" >&2
  echo "$changes" >&2
  exit 1
fi
echo "Clean - safe to release"

The script prints a short status with branch info, then uses lock-free porcelain output to exit with an error if anything is staged, modified or untracked.

When to use it

Review before committing

Before running git commit, check which files are staged and which edits you still need to git add.

CI clean-tree check

After a build or code generation step, have the pipeline run git status --porcelain and fail if any files changed unexpectedly.

Shell prompt or IDE integration

Show the branch, ahead/behind counts and dirty state using --porcelain=v2 --branch, and run it with --no-optional-locks so it doesn't block other Git processes.

Resolving merge conflicts

Find the unmerged paths (UU, AA and similar codes) that still need resolving before you finish a merge, rebase or cherry-pick.

Interview questions

QWhat three sets of paths does git status report?

First, paths that differ between HEAD and the index; these are what a commit would record. Second, paths that differ between the index and the working tree. Third, untracked files that are not ignored. You would have to git add the second and third groups before committing them.

Follow-up: How do you see the actual content changes and not just file names? Pass -v to include the staged diff, like git diff --cached, and pass -v -v to add the unstaged diff too.

QIn the short format, what do 'M ', ' M' and '??' mean?

The left character X is the index, and the right character Y is the working tree. 'M ' means the change is staged and the working tree matches the index. ' M' means the file was modified but not staged. '??' means the file is untracked.

Follow-up: What does 'UU' mean? It is an unmerged path where both sides of the merge modified the file, so the conflict still needs to be resolved.

QWhy use --porcelain in scripts instead of the default output?

The long format is meant for people and may change at any time. Porcelain output is guaranteed to stay backward-compatible and ignores user settings such as color.status and status.relativePaths. For filenames with unusual characters, add -z so entries end with NUL and nothing is quoted.

Follow-up: When would you choose v2 over v1? Choose v2 when you need branch headers (oid, head, upstream, ahead/behind), file modes and object names, or rename scores with the original path.

  • git add
  • git diff
  • git commit
  • git restore
  • git stash
  • git update-index
  • gitignore
  • git-config

Source: Git - git-status Documentation. Checked 2026-11-02.