EduFlow
Git & GitHub
0%

Section 1 · Git's Model

The Three Areas: Working Tree, Index, Repository

16 min4 min readFill in the blanks

Lesson at a glance

Move changes deliberately between the working tree, the staging area and the repository, check each step with status and diff, and split messy work into focused commits.

  1. 1Three places your work can be
  2. 2Seeing the difference: status and two diffs
  3. 3Splitting one file into two commits
  4. 4How big should a commit be?
  5. 5Short status, and backing out

No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.

You spent an evening on the portfolio. You added a navigation bar to index.html, created styles.css, and fixed a typo in your name along the way. That’s three unrelated changes. If you commit them together as “updates”, future you can’t undo the nav without also undoing the typo fix. Git gives you a place to sort changes before they become history.

Three places your work can be

Every change in a Git project lives in one of three places:

  • The working tree is the files on disk, the ones your editor opens. You can change them freely; Git only watches.
  • The index, also called the staging area, is the next commit being assembled. git add copies a file’s current content into it.
  • The repository is the commits already recorded, inside .git. git commit turns the index into a new commit.
Three boxes left to right: working tree, index (staging area), repository. git add moves from working tree to index, git commit from index to repository. Below, git restore --staged moves from repository back to the index, and git restore moves from index back to the working tree. Working tree files on disk Index next commit Repository recorded commits git add git commit git restore --staged git restore Dashed: copying back. git restore overwrites your file.
Commands move content between the three areas

After a commit, the index isn’t emptied. It still holds the full snapshot you just committed, so it matches the last commit until you stage something new. That’s why “staged changes” means the difference between the index and the last commit.

Seeing the difference: status and two diffs

Here’s the evening’s work, checked with git status:

Text
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   index.html

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	styles.css

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

git status tells you which files differ. To see the lines, use git diff, and remember there are two comparisons:

Terminal
git diff            # working tree vs index: what you haven't staged yet
git diff --staged   # index vs last commit: what the next commit will contain

--cached is an older synonym for --staged; you’ll see both in tutorials. Get into the habit of running git diff --staged right before every commit. It’s the last moment to notice a stray console.log or a file that doesn’t belong.

Splitting one file into two commits

The typo fix and the nav bar are both in index.html. git add index.html would stage both. Stage just the typo instead:

Terminal
git add -p index.html

Git shows each changed block, called a hunk, and asks Stage this hunk [y,n,q,a,d,s,e,?]? (newer versions list a few more letters; ? explains them all). Answer y for the typo hunk and n for the nav hunk (s splits a hunk that’s too big). Then:

Terminal
git diff --staged          # only the typo fix
git commit -m "Fix spelling of name in header"
git add index.html styles.css
git commit -m "Add navigation bar with base styles"

Two commits, each with one purpose. Later, if the nav bar needs to go, you can undo that commit alone.

How big should a commit be?

A good commit does one thing you could describe in a short sentence without the word “and”. “Fix spelling of name in header” passes. “Add nav, fix typo, tweak colours” fails, and the failure shows up later: when the colours turn out wrong, undoing that commit also removes the nav and brings back the typo.

There’s no line limit. A commit that renames a CSS class across twelve files is still one idea, and splitting it would leave the site broken in between. Aim for commits where the project still works before and after, each one a step you could explain to a reviewer in one breath. You’ll appreciate this in section 4, when undoing a single commit becomes a one-line command instead of an afternoon of surgery.

Short status, and backing out

git status -s packs the same information into two columns: the left is the index versus the last commit, the right is the working tree versus the index.

Text
M  README.md
 M index.html
MM styles.css
?? projects.html

README.md is staged; index.html has unstaged changes; styles.css has some of each; projects.html is untracked.

To take a file out of the index without losing your edits, use git restore --staged styles.css. To throw away unstaged edits and go back to the index version, use git restore styles.css. The second one is the only command in this lesson that destroys work: changes that were never staged or committed can’t be recovered.

You can now record exactly the history you mean to. Next you’ll read that history back, and see why Git calls it a graph rather than a list.

Key takeaways

  • The working tree is your files, the index (staging area) is the next commit being assembled, and the repository is the commits already recorded.
  • git diff compares the working tree to the index; git diff --staged compares the index to the last commit.
  • git add -p stages part of a file, so one messy editing session can become several focused commits.
  • git restore --staged <file> unstages and keeps your edits; git restore <file> throws your unstaged edits away.
  • git commit -a stages modified tracked files only; brand-new files still need git add.

Further reading

Check your understanding

4 questions

Question 1 of 4

You staged index.html, then edited it again. git diff shows only the second edit. Why?

Question 2 of 4

You ran git add styles.css but want it in the next commit after all, not this one. Which command keeps your edits and only unstages the file?

Question 3 of 4

You created projects.html and edited index.html, then ran git commit -am "Add projects page". What did the commit contain?

Question 4 of 4

In git status -s, what does the line MM index.html tell you?

Practice

Fill in the blanks

Stage on purpose

Complete the session. You stage only part of index.html (the typo fix), check exactly what will be committed, commit it, then stage the nav work but take styles.css back out of the index without losing your edits.

git status git add index.html # stage only the typo-fix hunk git diff # check what the next commit contains git commit -m "Fix spelling of name in header" git add index.html styles.css git restore styles.css # oops: unstage it, keep the edits git commit -m "Add navigation bar"