Git Course 0%

File states

Beginner Core Git Git CLI ≈ 8 min

What you will learn

  • The states of a file and what each means in terms of the areas
  • Which command moves a file from one state to the next, and which moves it back
  • How deleted, renamed and ignored files appear

After this lesson you can

  • I can look at any git status output and name every file's state
  • I know the next command for each state

Why this matters

git status describes files in terms of states, and every Git command that touches files moves them from one state to another. Learn the map once and you can predict what any command will do before you run it.

The states

File states and the commands that move a file between them Four states in a row: Untracked, Unmodified, Modified, Staged. git add moves untracked or modified files to staged. Editing moves an unmodified file to modified. git commit moves staged files to unmodified. git restore moves a modified file back to unmodified, and git restore --staged moves a staged file back to modified. git rm removes a file from tracking. Ignored files sit outside the cycle. Untracked Unmodifiedsame as last commit Modified Staged git add edit git add git commit git restore restore --staged git rm --cached Ignored listed in .gitignore outside the cycle: Git pretends the file does not exist Orange arrows discard or unstage; the restore command cannot be undone for uncommitted edits.
The states of a file and the commands that move it. Orange arrows discard or unstage.
State Meaning git status shows it as
Untracked The file exists in the working tree; Git has never been told about it under Untracked files:
Unmodified (tracked, clean) Tracked, and identical to the last commit nothing (the file is not mentioned)
Modified Tracked, changed in the working tree, not yet staged under Changes not staged for commit:
Staged The change has been copied to the staging area and will be in the next commit under Changes to be committed:
Ignored Matches .gitignore; Git pretends it does not exist nothing, unless --ignored

A file that was staged and then edited again is in two states at once (staged with the older content, modified with the newer), and appears in both groups.

The moves

From To Command Reverse
Untracked Staged git add <file> git rm --cached <file> (before the first commit) or git restore --staged <file>
Unmodified Modified edit the file in any editor git restore <file> (discards the edit, no undo)
Modified Staged git add <file> git restore --staged <file> (keeps the edit)
Staged Unmodified git commit git revert or git reset on the commit (Section 12)
Tracked Untracked git rm --cached <file> git add <file>
Any Ignored add a pattern to .gitignore remove the pattern

Two of these are the only ones that lose work: git restore <file> throws away uncommitted edits, and git rm variants remove files. Everything else is reversible.

Deleted and renamed files

Deleting a tracked file with your editor or with rm makes Git report it as deleted in the modified group; staging the deletion (git add <file> works for deletions too, or git rm <file> does both steps) moves it to the staged group:

Terminal
$ git status
On branch main
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	deleted:    docs/faq.md

no changes added to commit (use "git add" and/or "git commit -a")

Renaming or moving with git mv stages the rename directly; renaming in the editor produces a deletion plus an untracked file, which Git recognizes as a rename once both are staged:

Terminal
$ git mv docs/faq.md docs/questions.md
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    docs/faq.md -> docs/questions.md

Lesson 4.2 practises these.

Ignored files

Anything matching a pattern in .gitignore never appears in git status and is skipped by git add .. The playground ignores __pycache__/, .venv/, .env and editor folders. To see what is being hidden:

Terminal
$ git status --ignored

Ignored files are still on your disk; Git just looks away. If a file you need is missing from git status, --ignored is the first thing to check.

Common mistakes

  • Reading "nothing to commit" as "the file is not tracked". It means every tracked file is unmodified. An untracked file would be listed.
  • Using git restore to unstage. Without --staged it discards edits instead. Read the hint lines in git status; they always name the right form.
  • Adding a pattern to .gitignore for a file that is already tracked. Tracked files stay tracked; run git rm --cached <file> once, then the pattern applies.

Try it yourself

Goal: move one file through every state and watch git status change.

  1. In the playground, create docs/notes.md with one line; run git status -s (untracked, ??).
  2. git add docs/notes.md; run git status -s (staged new file, A).
  3. git commit -m "docs: add notes"; run git status -s (nothing: unmodified).
  4. Add a second line to the file; git status -s (modified, M).
  5. git add docs/notes.md; then add a third line; git status -s (both: MM).
  6. git restore --staged docs/notes.md, then git restore docs/notes.md; git status -s (nothing).

Expected result: the short-status codes change from ?? to A, to nothing, to M, to MM, and back to nothing.

Show solution

The two-column short format shows the staging area in the first column and the working tree in the second: A staged new file; M modified only in the working tree; MM staged and modified again; ?? untracked. Step 6 first unstages (keeping the edits), then discards the edits; the file is back to its committed content.

Check yourself

1. git status -s shows M docs/faq.md (a space, then M). The file is…
2. Which command turns a modified file back into an unmodified one, discarding the edit?
3. You added *.log to .gitignore but app.log still shows as modified. Why?

Key terms

Untracked Tracked Modified Staged Ignored .gitignore Restore