SovranCode
HomeCourses Git & GitHub Git Diff
This device
Course contentsGit Diff · 41 topics

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
Learn Git & GitHub40 complete · 1 planned

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
PREVIOUS LESSONGit Log
NEXT LESSONGit Reset
2. Git History 60 min

Git Diff

Compare unstaged, staged, and committed states so you can preview exactly what the next commit will record.

What you will leave with

You will be able to explain the three core diff comparisons, preview the next commit, compare revisions and branches, limit review to a path, read unified patch markers, and identify what diff intentionally does not show.

Every diff has two sides

LocateName whether a change is in the working tree, index, or a committed snapshot.
CompareSelect the exact pair of states that answers the review question.
ReadInterpret paths, hunks, context, additions, deletions, and metadata.
ProveReview the staged patch before recording the next commit.

Return to the three-state model

The working tree is the editable checkout on disk. The index is Git’s proposed next snapshot. HEAD normally resolves to the current branch’s latest commit. A diff does not mean “show every change”; it means “compare these two named states.”

WORKING TREE

What exists on disk now

Your current tracked file content, including edits made after the latest staging operation.

INDEX

What is staged next

The proposed snapshot assembled by git add, which may differ from both disk and HEAD.

HEAD is a revision, not a folder

In an ordinary attached state, HEAD points through the current branch to a commit. That commit stores a project snapshot and parent metadata.

The three core comparisons

# Working tree compared with the index
git diff

# Index compared with HEAD
git diff --cached

# Working tree compared with HEAD
git diff HEAD

git diff

Working tree versus index. Read this as “what tracked edits have I not staged?”

git diff --cached

Index versus HEAD. Read this as “what patch is staged for the next ordinary commit?”

git diff HEAD

Working tree versus HEAD. Read this as “what tracked content differs from the current commit, staged or not?”

git status --short

A state summary, not a patch. Use it beside diff to find untracked paths and staged/unstaged combinations.

QUICK CHECK

Test what you learned

Type the command that shows the patch currently staged for the next commit.

One file can have staged and unstaged changes

Staging is not a permanent label attached to a filename. Git records file content in the index. If you stage a file and edit it again, the staged version remains in the index while the newer working copy contains an additional change.

  1. EDIT
    Change line A

    git diff shows line A because the working tree differs from the index.

  2. STAGE
    Run git add

    Line A moves into the index; cached diff now shows it.

  3. EDIT AGAIN
    Change line B

    Plain diff shows line B while cached diff still shows line A.

  4. REVIEW
    Choose deliberately

    Stage line B only if it belongs in the same coherent snapshot.

Run all three core comparisons when status displays both staged and unstaged changes for one path. No single default command tells the whole story.

Read a unified patch

diff --git a/src/greeting.js b/src/greeting.js
index 42f10ab..67d9a11 100644
--- a/src/greeting.js
+++ b/src/greeting.js
@@ -1,4 +1,5 @@
 export function greeting(name) {
-  return "Hello " + name;
+  const safeName = name.trim();
+  return `Hello ${safeName}`;
 }

--- a/ and +++ b/

Labels for the old and new sides of the file comparison. They are not arithmetic signs.

@@ -1,4 +1,5 @@

A hunk header describing the old and new line ranges represented in this patch section.

Space prefix

Unchanged context that helps Git and reviewers locate the surrounding code.

Minus and plus prefixes

Content removed from the old side and added to the new side. A modification is represented as removal plus addition.

A patch is derived

A commit stores a snapshot. Git derives a patch by comparing two snapshots or states; it does not store the colored diff as the commit’s primary content.

Understand untracked and newly staged files

Plain git diff does not print a brand-new untracked file because that path is not represented in the index side of the comparison. git status --short reports it as ??. Once you intentionally stage it, git diff --cached shows the complete new-file patch.

git status --short
# ?? src/new-helper.js

git add src/new-helper.js
git diff --cached -- src/new-helper.js
Do not stage blindly just to make diff see a file

Inspect the path and its contents first. Confirm it contains no credentials, private records, generated output, or oversized assets before adding it to the index.

Compare commits, branches, and tags

# Changes needed to move from the older commit to the newer commit
git diff 2a71b4c 8f42d91

# Commits can also be branches, tags, or other revision expressions
git diff main feature/search

# Restrict the comparison to one path
git diff main feature/search -- src/search.js

With two revisions, Git shows the changes needed to transform the first snapshot into the second. The command does not move HEAD, modify either branch, or imply which side is correct. Direction matters: reversing the revisions reverses additions and deletions.

TWO DOTS OR A SPACE

git diff A..B

For diff, this is effectively the same endpoint comparison as git diff A B: snapshot A against snapshot B.

THREE DOTS

git diff A...B

Compare B with the merge base of A and B. This often answers “what did B introduce since the histories diverged?”

Three dots differ between log and diff

git log A...B selects commits in the symmetric difference. git diff A...B compares the merge base with B. Read the command name before interpreting the notation.

QUICK CHECK

Test what you learned

Type the command that compares feature/search with its merge base against main.

Narrow and format the review

git diff --stat
git diff --name-status
git diff --word-diff
git diff --check

# Show more surrounding lines when context matters
git diff --unified=8

# Ignore whitespace-only changes only when that matches the review question
git diff --ignore-all-space

Summary formats help you orient yourself, but they do not replace reading the relevant patch. --stat gives a file-level size overview. --name-status names added, modified, deleted, and renamed paths. --word-diff can clarify prose changes. --check catches whitespace errors introduced by the patch.

Use a pathspec after -- to reduce noise: git diff -- src/ README.md. Path filtering answers a smaller question; it can hide related changes elsewhere, so return to the complete staged patch before committing.

Renames, binary files, and generated output

Renames are detected

Git stores snapshots, not a permanent rename event. Diff compares similar deleted and added content and may present a rename with a similarity score.

Binary content is summarized

Ordinary line patches may not be meaningful. Verify the file, source, size, rights, and whether it belongs in Git.

Generated files add noise

If policy requires committed output, review both source and output. Otherwise, ignore reproducible artifacts rather than burying behavior changes.

Whitespace options change evidence

Ignoring whitespace can reveal logic changes, but it can also hide meaningful formatting in whitespace-sensitive files.

Guided practice: build and review one snapshot

Use a disposable repository or your learning journal. Begin from a clean status and never use real secrets in practice files.

  1. 01
    Create two tracked files

    Add a README and a small source file, then commit the baseline.

  2. 02
    Make two coherent edits

    Change both files and use plain diff to explain every hunk against the index.

  3. 03
    Stage only one path

    Run cached diff and prove only that path is proposed for the next commit.

  4. 04
    Edit the staged path again

    Use plain diff, cached diff, and diff HEAD to identify the three distinct views.

  5. 05
    Review and commit

    Run git diff --cached --check, inspect the complete staged patch, and commit only when its message matches the evidence.

Say the comparison aloud

“Working tree versus index” and “index versus HEAD” are better debugging tools than memorizing which flag usually looked right.

Independent lab: audit a mixed working state

Create a disposable repository with at least three committed files. Produce a state containing one staged modification, one unstaged modification, one file with both staged and unstaged changes, and one untracked file. Then produce an audit that:

  1. Uses short status to classify all four paths.
  2. Uses plain diff to explain only the unstaged tracked patches.
  3. Uses cached diff to explain exactly what the next commit would record.
  4. Uses diff HEAD to explain the combined tracked difference.
  5. Uses a pathspec to inspect the file with both states independently.
  6. Runs --stat, --name-status, and --check and explains what each view omits.
  7. Creates a branch, makes one additional commit there, and compares it with main using both two-dot and three-dot diff forms.
  8. Leaves the repository in a clean state with two coherent commits you can explain.
Definition of done

Your notes name both sides of every comparison, distinguish status from patch content, account for the untracked file separately, and show that the staged patch matched each final commit message.

Common diff mistakes

Assuming empty means clean

Plain diff can be empty while staged or untracked changes exist. Check status and cached diff.

Reviewing only the file list

Name-status finds scope; it does not reveal unsafe values or incorrect behavior inside the patch.

Forgetting direction

git diff A B describes A transformed into B. Reverse the endpoints and the patch reverses.

Confusing log three-dot with diff

The same punctuation has command-specific meaning. Diff uses the merge base and second endpoint.

Hiding whitespace too early

Ignore options alter the evidence. Read the normal patch before deciding whitespace is irrelevant.

Committing without cached review

The working-tree patch is not necessarily the staged patch. Review the index directly.

Lesson review

You can now treat git diff as a precise comparison tool instead of one command with mysterious output. You can review unstaged work, inspect the proposed next snapshot, compare historical endpoints, read patch structure, and explain the limits of each view.

  • I can name both sides of plain, cached, and HEAD diff comparisons.
  • I use status to find untracked paths and diff to inspect tracked content changes.
  • I understand unified patch headers, context, additions, and deletions.
  • I can compare revisions and explain two-dot versus three-dot diff behavior.
  • I review the complete cached patch and whitespace check before committing.

Related lessons

  • Git Log — History names the commits a diff can compare.
  • Git Reset — Correct local state only after you can see it.
KNOWLEDGE CHECK

Check your diff model

Choose the comparison that matches each working-tree, index, or history question.

01What does plain git diff compare?
02Which command previews the patch currently staged for the next commit?
03A file has staged and unstaged edits. What does git diff HEAD show?
04Why put -- before a path in a diff command?
05Which command checks a patch for whitespace errors without staging it?
06Does plain git diff show the contents of a brand-new untracked file?
07What does A...B mean when used as git diff A...B?
PREVIOUS LESSONGit Log
NEXT LESSONGit Reset
ON THIS PAGEGit DiffEvery diff has two sidesReturn to the three-state modelThe three core comparisonsOne file can have staged and unstaged changesRead a unified patchUnderstand untracked and newly staged filesCompare commits, branches, and tagsNarrow and format the reviewRenames, binary files, and generated outputGuided practice: build and review one snapshotIndependent lab: audit a mixed working stateCommon diff mistakesLesson reviewKnowledge checkRelated lessons
Course contents