Inspecting State
Three commands answer "where am I?" in a repository: git status shows what has changed and what is staged right now, git diff shows the exact line-level changes, and git log shows the history that led here. They read state and change nothing.
Misreading repo state is the root cause of most accidental data loss — discarding the wrong file, resetting past work you meant to keep, committing half of what you intended. Reading state correctly is the cheap habit that prevents the expensive recovery, so these commands belong before every operation that changes anything.
Status
git status sorts your files into three buckets: staged (going into the next commit), modified-but-unstaged (changed on disk, not yet added), and untracked (Git has never seen them). It also tells you the branch and whether you are ahead of or behind the remote. git status -sb gives the same picture in a compact two-letter-per-file form once you know what the columns mean.
Diffing the Trees
The diff commands compare specific pairs of trees, and which pair you ask for is the whole point. git diff with no arguments compares the working tree to the index — your unstaged changes. git diff --staged compares the index to HEAD — what is staged and headed into the next commit. git diff <a> <b> compares any two commits. Asking for the wrong pair is why a change can look like it vanished.
Reading History
Bare git log dumps full commit entries newest-first, which buries the structure on any real repository. --oneline collapses each commit to one line, --graph draws the branch and merge topology, and --stat shows which files each commit touched. Filters narrow it down: --since, --author, -p to show each commit's diff, and -S<string> — the pickaxe — to find the commits where a given string entered or left the code.
Finding Who and When
git blame <file> annotates each line with the commit, author, and date that last changed it — useful for finding the commit and its reasoning, less useful as a way to assign fault, since a whitespace reformat can put an innocent author on every line. git show <commit> prints one commit in full: its message and its complete diff, which is the fastest way to see what a single commit actually did.
Following a Single File
A file's history can predate its current name. git log --follow <file> traces it across renames, so you see the full lifetime of the content rather than just the commits since the last git mv. Without --follow, history stops at the rename and the earlier work looks like it belongs to a different file.
git diff (no arguments) — compares the working tree to the index, so it shows only the changes you have not staged yet. Once you stage a change, it disappears from this view, which is exactly what makes people think it was lost.
git diff --staged (alias --cached) — compares the index to HEAD, so it shows what is staged and will go into the next commit. When a change "vanishes" from plain git diff after an add, this is the view that shows it.
- Running plain
git diffafter staging everything, seeing nothing, and concluding the changes were lost — they are staged, sogit diff --stagedis the correct view. - Browsing a large repo's history with bare
git logand getting lost, because without--oneline --graphthe branch topology is invisible. - Using
git blameto assign fault rather than to find the commit and its reasoning, missing that a reformat commit can mask the real author. - Hunting for when a string was introduced by scrolling through
git logby eye instead of usinggit log -S<string>, the pickaxe built for exactly that. - Reading
git logon a renamed file without--followand concluding the file has no history before the rename.
- Run
git statusbefore any state-changing command —reset,checkout,commit— to confirm what is staged. - Make
git log --oneline --graph --decorateyour default history view to see branches and merges at a glance. - Use
git diff --stagedto review precisely what a commit will contain before runninggit commit. - Use
git log -S<term>orgit log -G<regex>to find the commit that added or removed specific code. - Inspect one commit in full — message and diff — with
git show <commit>instead of guessing from the log summary.
hg status, hg diff, hg log, hg annotate (blame)Subversion svn status, svn diff, svn log, svn blamePerforce p4 status, p4 diff, p4 changes, p4 annotateFossil fossil status, fossil diff, fossil timelineKnowledge Check
You stage a change, then run plain git diff and see nothing. Where is the change?
- Staged — plain
git diffcompares working tree to index, so a staged change only shows undergit diff --staged - Lost — the act of staging deleted it from both the working tree and the index entirely
- In the previous commit, already recorded permanently against HEAD by the staging step itself the moment you ran it
- In the reflog, parked there and waiting for you to run a manual restore
What does git log --oneline --graph reveal that bare git log hides?
- The branch and merge topology — where branches diverged and rejoined — in a compact, scannable form
- The full multi-paragraph commit message body for each entry, which the
--onelineflag normally truncates away - Commits that are otherwise hidden from you by per-commit access control rules
- The remote's newer commits that you have not yet fetched down locally
When does the pickaxe git log -S<string> beat reading the log by hand?
- When you need the commit where a specific string was introduced or removed, found directly rather than by scrolling
- When you want the commits sorted by their author's name rather than by their commit date
- When the repository was shallow-cloned with a fixed depth limit, so its older history is therefore incomplete on disk
- When you need to see the staged but uncommitted changes shown alongside the committed ones
What can git blame reliably tell you, and what can it not?
- It tells you which commit last touched each line; it does not reliably tell you who is responsible, since a reformat can overwrite the real author
- It reliably tells you who originally wrote every single line, regardless of any later edits made to it
- It lists every commit that has ever touched the file at all, presented in full graph order with each contributing commit's subject line attached for context
- It shows the currently staged but still uncommitted edits annotated against each line before you have committed them anywhere
You got correct