What Does git status Do?
A complete, beginner-friendly walkthrough of Git's most-used command — what it actually checks, how it reads your repository internally, and how professional engineers use it every single day without thinking twice.
Imagine you’re editing a group document with ten other people, except nobody can see anyone else’s edits in real time. Before you make your next change, you’d want to know one thing above all else: what’s already different from the last saved version? That, in one sentence, is the entire job of git status. It is the single most-run command in Git — more than commit, more than push, more than pull — because it is the command that tells you where you stand before you do anything else. This guide breaks it down from the ground up: no prior Git knowledge assumed, every term explained in plain English, and enough internal detail that by the end you’ll understand not just what it shows you, but why it shows you exactly that.
1Core Concept: What Is git status?
git status is a read-only command in Git — the version control system used to track changes to files over time — that answers a single question: “Compared to the last thing I saved, what has changed in my project right now?” It does not save anything, undo anything, or send anything anywhere. It simply reports.
Think of Git like a photo album of your project. Every time you “commit,” you take a snapshot and glue it into the album. git status is like holding your project up next to the most recent photo and asking: “What’s different between what I’m holding now and what’s in that last picture?” It doesn’t take a new photo. It doesn’t rearrange the album. It just tells you what’s changed since the last snapshot.
To understand why this matters, picture a real, everyday scenario. You’re building a small website. Yesterday you saved (committed) a version with a working homepage. Today, before lunch, you edited the navigation bar, created a new file called about.html, and accidentally left a stray console.log in your JavaScript file. You’ve been distracted and can’t quite remember everything you touched. Running git status instantly lists: the navigation file as modified, about.html as untracked (brand new, Git doesn’t know about it yet), and reminds you nothing has been staged for the next snapshot. In three seconds, you have a complete, accurate picture of your workspace — something that would take real effort to reconstruct from memory alone.
Git was designed so that changes are never saved automatically. You decide exactly what goes into each snapshot. But that design only works if you can clearly see what’s different beforehand — otherwise you’d be flying blind. git status is the safety check that makes deliberate, controlled snapshots possible.
It helps to understand the three “zones” a file in a Git project can live in, because git status is essentially a report on which zone every file currently sits in:
Working Directory
The actual files on your computer — the ones you open, edit, and see in your file explorer. This is the “real world” copy.
Staging Area (Index)
A holding area where you place exactly the changes you want included in your next snapshot — like a shopping cart before checkout.
Repository (HEAD)
The permanent, saved history — the album of snapshots already taken. This is the last commit you made.
git status compares all three zones simultaneously and tells you, file by file, where the differences are. That’s the whole concept. Everything else in this article is detail on how it does that comparison and how to read what it tells you.
2How git status Works Internally
Under the hood, git status doesn’t “ask around” or check a log file — it performs a live, direct comparison of three data structures every time you run it. Understanding these three structures is the key to understanding almost everything else in Git, not just this one command.
Read the HEAD Commit’s Tree
Git looks at the most recent commit (called HEAD, short for “the tip of the branch you’re on”) and reads the complete snapshot of every file as it existed at that commit.
Read the Index (Staging Area)
Git reads a hidden file called the “index” — think of it as a lightweight table listing every file Git is tracking and a fingerprint of its staged content.
Scan the Working Directory
Git walks through your actual folders on disk and checks each tracked file’s current content and timestamp against what the index recorded.
Compute and Print Differences
Git compares HEAD-vs-Index (this tells you what’s “staged”) and Index-vs-Working-Directory (this tells you what’s “unstaged”), then prints a combined, human-readable report.
For speed, Git first compares file timestamps and sizes rather than re-reading every byte of every file. Only when a timestamp looks suspicious does it actually re-hash the file’s content to confirm whether anything really changed. This is why git status feels instant even on projects with tens of thousands of files.
Every file change in Git is ultimately tracked through a content fingerprint called a SHA-1 hash — a unique 40-character code generated from a file’s exact contents. If you change even a single character in a file, its hash changes completely. git status uses these hashes (by way of the index) to decide, with mathematical certainty rather than guesswork, whether a file is truly different from the last commit.
3Data Flow & Lifecycle of a File
It’s easier to understand git status by following one single file through its entire lifecycle — from the moment it’s created to the moment it’s safely committed.
flowchart LR
A["New file created\non disk"] -->|"git status shows:\nUntracked"| B["Working Directory"]
B -->|"git add"| C["Staging Area\n(Index)"]
C -->|"git status shows:\nChanges to be committed"| D{"Ready to\ncommit?"}
D -->|"git commit"| E["Repository (HEAD)\nPermanent snapshot"]
B -->|"edit tracked file"| F["git status shows:\nChanges not staged"]
F -->|"git add"| C
E -->|"edit again"| F
Fig 1 — The lifecycle of a file as it moves between the three zones git status inspects
Walking through this diagram in plain language: a brand-new file starts completely unknown to Git — this is the Untracked state. The moment you run git add on it, it moves into the staging area, and git status now reports it under “Changes to be committed.” If you go back and edit a file that Git already knows about (one that’s been committed before), it appears under “Changes not staged for commit” because the working directory now differs from what’s in the index. Only when you run git commit does the staged content become a permanent part of the repository’s history, and the cycle can begin again on the next edit.
Picture packing for a trip. Your closet is the working directory — full of clothes, some packed-ready and some not. Your open suitcase is the staging area — only what you’ve deliberately placed inside will travel with you. The trip itself (once you’ve zipped the suitcase and left) is the commit — a sealed, permanent record of exactly what you brought. git status is like glancing between your closet and your open suitcase and saying “these three shirts are packed, that jacket is still on the floor, and you just bought a new pair of shoes I don’t recognize yet.”
4Reading the Output
When you run git status in its default (long) form, it prints output organized into clearly labeled sections. Here is what each one means and, critically, why Git separates them the way it does.
Branch Information
The first line always tells you which branch you’re on, for example “On branch main.” Below that, Git may also tell you how many commits you are ahead of or behind a remote branch — useful for knowing whether you need to push or pull.
“Changes to be committed”
Files listed here are staged — they sit in the index, ready to become part of the next commit. This section only appears if you’ve run git add on at least one file since the last commit.
“Changes not staged for commit”
These are files Git already tracks (they exist in the last commit) but that you’ve edited since, and those edits haven’t been staged yet. Git even tells you the two commands you’ll most likely want next: git add to stage them, or git restore to discard the changes.
“Untracked files”
Brand-new files that exist on disk but that Git has never been told to track. Git will never include these in a commit until you explicitly run git add on them — this is a deliberate safety feature, not an oversight.
A file can only ever be listed in one category per comparison, but a single filename can appear in both the staged section and the unstaged section at the same time — this happens when you stage a change, then keep editing the same file afterward. Git is telling you, correctly, that part of your work is queued for the next commit and part is not.
5Options & Flags
Advanced Concepts
The default output of git status is friendly and verbose, which is great for learning but can feel slow to read once you’re working with it dozens of times a day. Git provides several flags to change how the information is presented, without ever changing what is actually being checked.
| Flag | What It Changes | When Engineers Use It |
|---|---|---|
-s / --short | Condenses each file to a single two-character code line instead of a paragraph | Quick daily glances once you know the codes |
-b | Adds branch and tracking info to short-format output | Combined with -s as -sb, a favorite for terminal prompts |
--porcelain | Produces a stable, script-friendly format that won’t change between Git versions | Automation, CI/CD pipelines, custom tooling |
--ignored | Also lists files excluded via .gitignore | Debugging why a file isn’t showing up as untracked |
-uno | Hides untracked files entirely | Very large repositories where scanning untracked files is slow |
“What’s the difference between the default status format and --porcelain, and why would a script prefer the latter?” — The expected answer: the default format is meant for humans and its wording can change across Git releases, while --porcelain guarantees a fixed, predictable structure specifically so that scripts and tools never break when Git is upgraded.
6Advantages, Disadvantages & Trade-offs
Advantages
- Completely safe — it is read-only and can never modify, delete, or lose data
- Extremely fast, even on large repositories, thanks to timestamp-based short-circuiting
- Gives a single, unified view across three separate data structures at once
- Prevents accidental commits by clearly separating staged from unstaged work
Limitations
- Only shows the current moment — it has no memory of what changed five minutes ago
- Doesn’t show the actual line-by-line content differences (that’s the job of
git diff) - Can feel slow on extremely large monorepos with hundreds of thousands of files, since it still has to scan the working directory
- Default output can feel verbose for experienced users running it constantly
The core trade-off is between completeness and speed of reading. The long-form output is deliberately educational and includes helper hints, which is perfect while learning, but professional engineers almost always switch to -sb or a shell-integrated short status once they’re comfortable, trading friendliness for speed of scanning.
7Best Practices
opening a terminal
every commit
merge operation
- Run it before you touch anything. Make it a reflex, the very first thing you do when returning to a project — it tells you whether you left work uncommitted last time.
- Run it before staging. Confirm what’s actually changed before running
git add, so you don’t accidentally stage files you didn’t mean to include. - Run it right before committing. A final check of the “Changes to be committed” section prevents half-finished or unrelated changes from sneaking into a commit.
- Use
.gitignorealongside it. If build artifacts or dependency folders keep cluttering your “untracked files” list, add them to.gitignoreso the output stays meaningful. - Pair it with
git diff. Usegit statusto see which files changed, thengit diffto see exactly what changed inside them.
8Common Mistakes & Gotchas
Mistake
Assuming a file listed as “untracked” is somehow already safe or backed up by Git.
Reality
Untracked files exist only on your disk. Git is completely unaware of their history and won’t protect them from accidental deletion until you explicitly stage and commit them.
Mistake
Committing without checking status first, then discovering unrelated debug files were swept into the commit.
Reality
Running git status immediately before git commit takes two seconds and catches this every time — it’s the cheapest insurance in the entire Git workflow.
Mistake
Expecting git status to show what changed inside a file.
Reality
git status only reports which files changed, not the content of the change. For line-by-line detail, the correct tool is git diff (for unstaged changes) or git diff --staged (for staged changes).
9Real-World Usage Patterns
Detecting Uncommitted Changes
Automated build systems (like GitHub Actions or Jenkins) often run git status --porcelain after a build step to check whether the build process generated any unexpected file changes, failing the pipeline if the output isn’t empty.
Live Branch Indicators
Popular terminal prompt tools (like Oh My Zsh or Starship) call git status -sb behind the scenes to show your current branch and a “dirty” indicator directly in your prompt, so you always know your state without typing a command.
Guarding Against Empty Commits
Teams write Git hooks that check git status before allowing a commit to proceed, blocking commits that would include nothing meaningful or that still contain merge-conflict markers.
Pre-Pull-Request Sanity Check
Before opening a pull request, engineers routinely run git status to confirm every intended file is staged and nothing stray (like a local config file) is about to be included.
10Frequently Asked Questions
11Summary and Key Takeaways
Key Takeaways
- git status is a read-only reporting command — it compares your working directory, the staging area (index), and the last commit (HEAD), and it never changes any of them.
- Every tracked file falls into one of a few clear states: staged (ready to commit), modified but unstaged, or untracked (unknown to Git entirely).
- Internally, Git uses content hashes and timestamp short-circuiting to compute these differences quickly, even on large projects.
- The default output is verbose and beginner-friendly; flags like
-s,-sb, and--porcelaintrade that friendliness for speed and scriptability. - Running it before staging and before every commit is one of the cheapest, highest-value habits in software engineering — it consistently prevents accidental or incomplete commits.
- It answers “what changed?”, not “what exactly changed inside the file?” — for content-level detail, pair it with
git diff. - Because it’s completely safe and non-destructive, there is never a reason not to run it — when in doubt, run
git status.